Git Product home page Git Product logo

swtbahn-cli's Introduction

SWTbahn Client-Server Command Line Interface

CI/CD Latest release

This is a client-server command line interface for the SWTbahn. The server is connected to the BiDiB interface and provides a REST API. The client side provides a command line interface which connects to the web service to execute the commands. The command line interface was developed by Nicolas Gross as part of his work for the libbidib project.

Dependencies

Server

  • C compiler
  • Libraries: onion, libpam, libgnutls, libgcrypt, libpthread, libglib-2.0, libyaml, libbidib
  • ForeC command line compiler: forecc
  • KIELER command line compiler: kico.jar
    • Path to the folder that contains kico.jar has to be defined in the environment variable KIELER_PATH
  • BahnDSL command line compiler: bahnc
    • Path to the folder that contains the bahnc has to be defined in the environment variable BAHNDSL_PATH
  • SCCharts verifier: SWTbahn Verifier (SWT internal repository)

Command Line Client

  • python3
  • Python libraries: click, requests, pyaml (pip3 install click requests pyaml)

Web Client

  • Web browser

Build

  1. Clone the repository
  2. Install the necessary dependencies (remember to run ldconfig after make install for libbidib if you are on Linux)
  3. Navigate to the directory where the build files should be generated
  4. Execute cmake <path-to-project-root>/server
  5. Execute make

Test

To run the unit tests, execute make test from within the build directory. Each unit test can be executed to display more detailed test results, e.g., ./server_bahn_util_tests.

Usage

Server

  1. Build the executable (see section Build)
  2. Create the configuration files for your track (see libbidib documentation)
  3. Connect the BiDiB interface to the server
  4. Check on which serial device the board is connected: dmesg | grep tty
  5. Start the server: ./swtbahn-server <serial-device> <config-directory> <IP> <port> (IP is the IP-address under which the server can be reached and port specifies on which port the server listens)
    For example: ./swtbahn-server /dev/ttyUSB0 ../../configurations/swtbahn-lite/ 141.13.106.27 2048
  6. Quit the server with Ctrl-C if you're done

Client (Command Line)

  1. The client is located under <project-root>/client/swtbahn

  2. Use the --help flag to get information about parameters, options, ...

  3. Use the config command to setup the client: swtbahn config <hostname> <port> <default-track-output>, where hostname is the IP and port the port which you used when you started the server. The is the name of the track output which should be used if no track output is explicitly specified when issuing a command.
    For example: ./swtbahn config 141.13.106.27 2048 master
    This will create a config file in the current working directory. Dont use the client from a different working directory for the current session, otherwise it won't find the configuration file. If you really want to use two logically different clients on the same device, you could just run the clients from different working directories which will lead to distinct configs.

  4. Now you can use the commands from the categories swtbahn admin, swtbahn controller, swtbahn driver and swtbahn monitor. If the system was not started by swtbahn admin startup, all the other commands won't work.

    For example:
    ./swtbahn admin startup
    ./swtbahn monitor get_segments
    ./swtbahn monitor get_trains
    ./swtbahn driver grab cargo
    ./swtbahn driver set_dcc_speed -b 5

  5. If you're done, you should shut the system down gracefully by invoking swtbahn admin shutdown

Client (Web Interface)

  1. Use a web browser to navigate to <IP>:<port>/assets/client.html
  2. Set the main track output (default is master).
  3. Click the Startup button.
  4. To be a train driver, select a train and click the Grab button. Enter a speed between 0 (stop) and 127 (max speed), and click the Drive button.
  5. To control a point, type the name of a point (see the YAML configuration file), select a position, and click the Set button.
  6. To control a signal, type the name of a signal (see the YAML configuration file), select an aspect, and click the Set button.

Logging into the Raspberry Pi remotely

Use ssh to the log in remotely. Suppose the Raspberry Pi is located at 141.13.106.30. Then use the command ssh [email protected].

Strategy for finding the IP address of the Raspberry Pi

There are two Raspberry Pis with the hostnames raspberrypi1 and raspberrypi2. The Raspberry Pi documentation lists several strategies for finding the IP address of a Raspberry Pi. If you change the Raspberry Pi's hostname, e.g., by editing /etc/hostname or by using the Raspberry Pi Configuration application, Avahi will automatically change the .local mDNS address. The MAC address of all Raspberry Pis begin with b8:27:eb.

  1. macOS: Try and resolve the Raspberry Pi's hostname, e.g., raspberrypi1.local, with multicast DNS:

    ping raspberrypi1.local

    If this fails, try the strategy for Linux.

  2. Linux: Use ifconfig to find your subnet, e.g., 192.168.1._. Use the nmap command to scan your subnet for connected devices, and look for the Raspberry Pi's hostname in the results:

    nmap -sn 192.168.1.0/24

  3. Windows: Use ipconfig to find your subnet, e.g., 192.168.1._. Install nmap and open the command line as an administrator for nmap to display the hostnames in its results. Use the nmap command to scan your subnet for connected devices, and look for the Raspberry Pi's hostname in the results:

    nmap -sn 192.168.1.0/24

    Use the command nmap -sn 192.168.1.0/24 | findstr /i "b8:27:eb" to quickly see a list of Raspberry Pis (MAC addresses only).

Sending files from the Raspberry Pi to a client computer:

Use scp on your client computer. For example, suppose the Raspberry Pi is located at 141.13.106.30 and has the user pi. To copy the the file /var/log/syslog from the Raspberry Pi via the user pi, use the command scp [email protected]:/var/log/syslog syslog

Verification

Train engines (and ther plugins) defined as SCCharts (*.sctx) files can be verified against certain properties before they are uploaded to the sever. Verification is on by default and can be configured to true (On) or false (Off) via the /admin/set-verification-option endpoint. For the command line client, use the command swtbahn admin set-verification-option <true/false>.

When verification has been turned on and an SCCharts file is uploaded, the server sends a request to SWTbahn Verifier (SWT internal repository), which...

  1. checks that the SCCharts file defines a set of safety properties (invariants, LTLs),
  2. compiles the SCCharts file to a format that can be verified (e.g., using nuSmv),
  3. verifies the safety properties, and
  4. sends verification results back to the server.

If all safety properties hold, the server processes the SCCharts file, e.g., by compiling and loading the file as a plugin. Otherwise, if any safety property does not hold, the server does not process the SCCharts file any further and reports the failure to the client.

The sever communicates with SWTbahn Verifier via websockets with JSON messages. A typical verification session is as follows:

  1. swtbahn-cli server receives an upload request for an SCCharts file;
  2. swtbahn-cli server establishes a websocket connection with SWTbahn Verifier;
  3. swtbahn-cli server sends the SCCharts file as a JSON message to SWTbahn Verifier;
  4. SWTbahn Verifier responds by either
    1. acknowledging the request to verify the SCCharts file and proceeding with the verification, or
    2. rejecting the request;
  5. swtbahn-cli responds by either
    1. waiting for the verification results on the websocket connection, or
    2. stopping the processing of the SCCharts file;
  6. for the case that SWTbahn Verifier proceeded with the verification, after the verification has finished, SWTbahn Verifier sends the results as a JSON message to the swtbahn-cli server; and
  7. swtbahn-cli receives the results, closes the websocket connection, and processes the results.

Grab-id and session-id behaviour

Grab-ids are used as tokens for trains. A client needs to grab a train before he can invoke commands for controlling the train. A train could only be grabbed by one client at a time.
Session-ids are used to check wether a grab-id was given out to the client on the current session or on a previous session.

Server side

When is a new session-id created?

  • If a user issues swtbahn admin startup and the system is not running already

When is the session-id invalidated?

  • If a user issues swtbahn admin shutdown

When is a grab-id created?

  • If a client issues swtbahn driver grab <train> and the train is available

When is a grab-id invalidated?

  • If a client issues swtbahn driver release and the train was grabbed by this client

Client side

When is the session-id fetched?

  • If the user issues swtbahn driver grab <train> and the train is available and the client has not already grabbed a train

When is the session-id reset?

  • If the user issues swtbahn driver release
  • If the user issues any swtbahn driver command and the session-id or grab-id is not the same as the one at the server
  • If the user issues swtbahn admin shutdown and the system was running
  • If the user issues swtbahn config

When is a grab-id fetched?

  • If the user issues swtbahn driver grab <train> and the train is available and the client has not already grabbed a train

When is a grab-id reset?

  • If the user issues swtbahn driver release
  • If the user issues any swtbahn driver command and the session-id or grab-id is not the same as the one at the server
  • If the user issues swtbahn admin shutdown and the system was running
  • If the user issues swtbahn config

Logging Format Notes

We try to use a consistent logging format in all request handlers. General workflow of how request handlers generate log messages:

  1. Parse form data.
  2. Validate form data. If validation fails, make a log on ERROR level and stop processing.
  3. Make a log on log level NOTICE that represents the start of processing, with - start at the end of the log.
  4. Process request. If processing causes an error, make a log on the ERROR or WARNING log level with - abort at the end of the log and stop processing.
  5. Processing concluded. Indicate this by printing the log message of Step 3 again, on the same log level, with - finish instead of - start at the end.

For request handlers that barely do any "processing" at all; e.g. where only a status variable is updated, they only generate one log message that ends with - done. Request handlers that only return information (getters) also use the - done pattern instead of start and finish, and use the log level INFO for the - done log.

As an example, when a request is made to set point10 to the normal state, the request handler (handler_set_point) generates the following log messages when the processing is successful:

LOG_NOTICE: Request: Set point - point: point10 state: normal - start
Intervening log messages from internal processing
LOG_NOTICE: Request: Set point - point: point10 state: normal - finish

If the above request was instead made with an unsupported state, e.g., foobar, then the request handler would generate the following log messages to say that the processing was stopped because of invalid parameters:

LOG_NOTICE: Request: Set point - point: point10 state: foobar - start
Intervening log messages from internal processing
LOG_ERR: Request: Set point - point: point10 state: foobar - invalid parameters - abort

If the above request forgot to specify the state, i.e., the state parameter is null, then the request handler would only generate the following log message to say that the parameter validation failed:

LOG_ERR: Request: Set point - invalid parameters

swtbahn-cli's People

Contributors

bluedtke avatar clehanka avatar dependabot[bot] avatar eyip002 avatar hosakb avatar jboockmann avatar nicolasgross avatar noriakisana avatar trinnguyen avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

swtbahn-cli's Issues

Game Client: Improve Instructions for the simple driver client

For better understanding of the system, it would be nice to add some kind of instructions when you visit the simple driver client (also called "game" client in the past). Explanations should be displayed next to the interface elements they are referring to. Furthermore, the Emergency brake/auto-stop message should be improved to better convey why the train was stopped at this point.

  • Destination Selection
  • Destination/Signal symbol whilst driving
  • Emergency Stop/signal overrun

Incorrect Check if Engine/Interlocker is invalid/unremovable in server / handler_upload.c

File in question: server/src/handler_upload.c

Description: In the methods handler_remove_engine and handler_remove_interlocker, we want to NOT fulfill the request if the name of the object to remove is null OR the name equals the name of the default object which is supposed to be unremovable.

In handler_remove_engine, the check looks like this:
if (name == NULL && engine_is_unremovable(name)) { //not allowed, error message }
which means: If the name is null AND the name matches the name of the default object which shouldn't be removed. This should be an OR instead. Because the name of the default object is not 'null', this if condition can never evaluate to true.

The problem is pretty much the same in handler_remove_interlocker; a logical OR needs to be used instead of a logical AND.

Consequences: If this is not corrected, the default (supposedly unremovable) objects could maybe be deleted.

Fix: Switch && to ||.

Likely Memory Leak in handler_driver is_forward_driving function

Branch: game
In the source file handler_driver, in function is_forward_driving, on line 134, a bidib query is made: t_bidib_id_list_query rev_query = bidib_get_connected_reversers();.
The struct in question holds a member of type char**. Bidib documentation says that the caller shall free the memory allocated. This is not done (afaics). Same thing with the query on line 142/143 in the same function.

Get routing information

  • Update extra_config.yml with better orientation information for overlaps and signals involved
  • Add a monitor function (get_block(block_id, orientation)) to return an array of signal and segments in their order of occurrence according to orientation
  • Update YAML parser for interlocking table (signals) and extras (signals and segments)
  • Implement bool is_type_segment(const char *id)
  • Implement bool is_type_signal(const char *id)
  • Extend the monitor with methods to query whether an id is a segment or signal

Clean up Interlocker Dynamic Library

  • server/src/dynlib.c
    • dynlib_load_interlocking: proper error checking
  • interlocking_algorithm.c
    • No longer needed
  • interlocking_bahndsl.c
    • Integrate into dynamic containers and handler_controller
  • bahn_data_util.h
    • rename initialise_config, free_config, init_cached_track_state, free_cached_track_state with bahn_data_util namespace
  • interlocking.c
    • remove uses of get_route_str
  • Rename interlocking to interlocker
  • Rename src/interlocking to src/interlockers
  • Make sure that bin/engines and bin/interlockers are removed on "make clean"
  • Fix whitespaces

Python Client is missing engine upload and deletion functionality

The Python-client implements methods for most admin/controller/driver/monitor endpoints offered by the server. However, engine and interlocker upload and deletion is not implemented.

I will add engine upload/deletion to the Python client in a new development branch. I'll take a look if the same can be done for interlocker upload/deletion. Finally, I'll create a pull request once it is confirmed to work as expected.

header files missing includes

Some .h files in the server source do not import/#include the headers where the types used are defined. This is completely fine for compilation, as the includes are dealt with as part of .c files and build setup.
However, language servers such as clangd will complain about missing type definitions when working on the codebase in, e.g., VSCode. A quality-of-life improvement would be to add the necessary imports to the headers.

The headers in question are, as far as I can see:

  • dyn_containers
  • track_config_parser
  • handler_admin
  • handler_controller
  • handler_upload
  • tick_data

I'm not sure if dyn_containers and tick_data don't have any includes for ForeC-toolchain related reasons.

Inconsistent assignment of values for platformlights in YAML configuration file

In configurations/swtbahn-standard/bidib_track_config.yml, the assignment of values to platformlights' on/off ids are inconsistent to those used for the sync and lanterns.

Change the values for on/off below ...

- id: platformlights
number: 0x0A
aspects:
- id: on
value: 0x01
- id: off
value: 0x00
initial: on

... to be consistent with ...
- id: sync2
number: 0x06
aspects:
- id: off
value: 0x01
- id: on
value: 0x00
initial: on
- id: lanterns2
number: 0x07
aspects:
- id: off
value: 0x01
- id: on
value: 0x00
initial: on

Server Crash after Shutdown followed by startup

SWTbahn Server crashes after Shutdown has been press, followed by a another Startup of the System.

This issue occured after the following input combination:
Ping (OK) -> Startup (OK) -> Shutdown (OK) -> Ping (OK) -> Grab Train (System not running or train not available!)
-> Startup (OK -> Server Crash) [GLib:ERROR:../../../glib/ghash.c:377:g_hash_table_lookup_node: assertion failed: (!g_atomic_ref_count_compare (&hash_table->ref_count, 0))
Aborted] {BIDIB Lights}

Fixed by @eyip002

what board am I API endpoint

Add an endpoint that returns the name of the model railway (e.g., swtbahn-full).

This name is currently not defined in the config files; one workaround could be to use the name of the folder the config files are located in.

Replace Driving Direction Option in the Clients

When trains stop, their headlights no longer switch back to their physical forward direction. For example, when a train reverses and then stops, the train headlights remain in the reverse direction. Thus, it is no longer possible to know the physical direction of the train.

  • Remove the backwards option when setting train speed
  • Add option to swap the train head with its tail

Only Allow Interlockers to Execute When Route Granting Is Needed

Interlockers cannot be run continuously because they will keep granting the same routes according to their inputs.

  • Don't execute an interlocker instance once its output_terminated == true && strncmp(interlocker_instance->output_return_code, "") != 0
  • Reset interlocker instance before each route request

Game client: Improve handling of server disconnection

Give feedback to the user when their connection to the server is broken, either because of an internet disconnection or server restart:

  • Client device has lost internet disconnection: Display modal warning dialog saying that their internet has been disconnected, with a Reconnect button to try and reconnect to the server
  • Server restart (shutdown + startup): Session ID on the client becomes expired and the user has to reload the webpage. Display a modal warning dialog with a Reload button saying that the user has to reload the page.

Reverser status cannot be read if no train is on the reverser

Via the request on endpoint monitor/reversers, we should be able to get status information on the reversers. For this, the startup command must've been sent before, and there must exist at least one reverser on the track and in the config.

On our SWTbahn-Full, we only get the expected reply (containing the reverser status) iff a train is on the segments related to/wired to the reverser. If a train is somewhere else on the track, we get OCS_NOT_IMPLEMENTED (i.e. line 432) and the server logs Request: Get reversers - unable to request state update. In other words, the reversers_state_update call returns true.

From looking at the reversers_state_update implementation, the way that the return works does not reveal where exactly the error occurred. Either bidib_request_reverser_state returns the error, or all queries that succeed have the state value BIDIB_REV_EXEC_STATE_UNKNOWN.

My suspicion is that this is either due to libbidib, or the protocol working in a different way than expected.

Host web-client dependencies locally

Currently, for the swtbahn-cli web-client, the jQuery and Bootstrap dependencies are loaded from a CDN.

Firstly, this is problematic if the model railway is to be used with no internet connection, for example when the clients connect via a hotspot offered by the same device that the server is running on.

Secondly, it might be problematic regarding EU data protection laws.

To be on the safe side, we shall try serving Bootstrap and jQuery locally. For this, we have to test whether the page loading speed is negatively impacted, and whether this is legal/possible from a license standpoint.

drive_route function may run indefinitely if train is lost temporarily during driving

This issue concerns the drive_route function as present starting on line 107 in file server/src/handler_driver.c.

The loop commented with "// Wait until the next segment is entered" (Line 152) can only ever be exited if the server is being shut down or if the train enters one particular 'next' segment (path_item). When driving in practice, the train is sometimes lost or recognized as a different train for a few seconds. If the train passes over the expected next segment during this time, the loop will never be exited (until shutdown).

Outline for possible solution: Check for entering of any segments still "left" on the route. If a segment further ahead is entered, skip looking for the current segment. Note: This must be implemented with routes in mind that can enter the same segment twice along a route.

Forward Server Error Messages to Client

The simple web clients in /server/src/assets report a generic error message when the server encounters a problem. The server logs more detailed error messages to syslog, which should also be passed as a response to the web clients.

Potential Deadlocks

Debugging an unresponsive swtbahn-server:

  • Execute the server through a debugger:
    • gdb ./swtbahn-server and then run /dev/ttyUSB0 ../../configurations/swtbahn-standard/ localhost 8080, or
    • lldb ./swtbahn-server /dev/ttyUSB0 ../../configurations/swtbahn-standard/ localhost 8080
  • Start the Python client: ./swtbahn config localhost 8080 master
  • When the server becomes unresponsive, use the Python client to get debugging information about the dynamic train engine containers: ./swtbahn monitor get-debug-info
  • Abort the server using ctrl-c
  • bt for backtrace
  • info threads to see all threads
  • thread ID to switch to the backtrack of thread ID

Backtraces generated when swtbahn-server becomes unresponsive:

#3  0x0002981c in dyn_containers_set_train_engine_instance (grabbed_train=0x4a28c <grabbed_trains>, train=0xb2b64426 "cargo_db", engine=0xb2b64436 "libtrain_engine_default (unremovable)")
    at /home/pi/Desktop/SWTbahn/swtbahn-cli/server/src/dyn_containers_interface.c:388
#4  0x0002cae8 in grab_train (train=<optimized out>, engine=<optimized out>) at /home/pi/Desktop/SWTbahn/swtbahn-cli/server/src/handler_driver.c:287
#2  0x76a52fb0 in usleep (useconds=<optimized out>)
    at ../sysdeps/posix/usleep.c:32
#3  0x00019a80 in dyn_containers_set_train_engine_instance ()
#4  0x0001d7a4 in grab_train ()
#2  0x76a52fb0 in usleep (useconds=<optimized out>)
    at ../sysdeps/posix/usleep.c:32
#3  0x00019c2c in dyn_containers_free_train_engine_instance ()
#4  0x0001d2b0 in free_train ()

Probably fixed:

#1  0x76cb5f44 in __GI___pthread_mutex_lock (
    mutex=0x3d3e0 <grabbed_trains_mutex>) at pthread_mutex_lock.c:80
#2  0x0001d5e4 in grab_train ()
#1  0xb6cb9f44 in __GI___pthread_mutex_lock (mutex=0x3a3e#0  __lll_lock_wait (futex=futex@entry=0x3a3e8 <grabbed_trains_mutex>, private=0) at lowlevellock.c:438 <grabbed_trains_mutex>)
    at pthread_mutex_lock.c:80
#2  0x0001c6cc in train_grabbed (train=0xf9c06 "cargo_db")
    at /home/pi/Desktop/SWTbahn/swtbahn-cli/server/src/handler_driver.c:79
#1  0x76cb5f44 in __GI___pthread_mutex_lock (mutex=0x3e3bc <start_stop_mutex>)
    at pthread_mutex_lock.c:80
#2  0x0001b928 in handler_startup ()
#2  0x76a4ffb0 in usleep (useconds=<optimized out>) at ../sysdeps/posix/usleep.c:32
#3  0x0001aa80 in dyn_containers_free_interlocker_instance ()
#4  0x0001c30c in free_all_interlockers ()

File upload after startup fails after file upload without startup

File Upload failed after pressing file upload before startup, followed by a file upload after pressing the Startup button.

The Bug occured after the following inpuit combination.
Upload (Engine train_engine_eugene.sctx could not be compiled or loaded!) -> Startup (OK) -> Upload (Engine train_engine_eugene.sctx could not be compiled or loaded!) -> Startup (System already running!)

This bug could not be reproduced.

Make Kieler and BahnC Discovery/Invocation Consistent

In dynlib.c, Kieler is referred to/found via the expected environment variable "KIELER_PATH": [..] java -jar \"$KIELER_PATH\"/kico.jar [...]
Meanwhile, BahnC is expected to be on the path: bahnc -o %s/bahnc [..].

This should be made consistent, and we should add this information (the need for these variables) to the README.

Properly configure board peripherals

peripherals onecontrol1
peripheral sync1 0x06
peripheral lanterns1 0x07
end
peripherals onecontrol2
platformlight sync2 0x06
platformlight lanterns2 0x07
end

The peripherals should all be of type peripheral. Extend peripherals to support required GPIO port (high and low) address (0x????).

peripherals onecontrol1
  onebit sync1 0x06 port 0x0027
  onebit lanterns1 0x07 port 0x0018  # Exact port address is not essential
end

peripherals onecontrol2
  onebit sync2 0x06 port 0x0027
  onebit lanterns2 0x07 port 0x0018  # Exact port address is not essential
end
peripherals:
  - id: sync2
    number: 0x06
    port: 0x0027
    aspects:
      - id: on
        value: 0x00
      - id: off
        value: 0x01
    initial: on
    type: onebit
  - id: lanterns2
    number: 0x07
    port: 0x0018
    aspects:
      - id: on
        value: 0x00
      - id: off
        value: 0x01
    initial: on
    type: onebit

Precompiled default interlocker and train libraries do not work on (Linux) x86_64

When startup is called for a running swtbahn-cli server, the default interlocker libraries and the default train-engine libraries are loaded dynamically. The lib files are located at server/src/interlockers and server/src/engines respectively (.so and .dylib files).

These shared libraries were compiled on a particular device at some point. Not sure exactly where/how. Regardless, the current precompiled libraries can't be loaded when running the swtbahn-cli server on an x86_64 linux device (in this case, running Kubuntu 22.04 with kernel 5.15.0-46). Loading them results in header/ELX (ELF?) conflicts, which is not particularly suprising, assuming that they were compiled on a different architecture and with a different kernel.

To be able to run the swtbahn-cli server on an x86_64 linux device, one has to re-compile new default engines and interlockers, and place them in the appropriate locations. Whilst that is technically possible, there is no source file for the default train engines, at least not in this repository. For the interlockers, there are two source files which can be used.

I see multiple possible solutions:

  • Supply the source for default train engines and re-compile them on demand upon startup, should loading the default libraries fail
  • Supply additional precompiled libraries explicitly for x86_64, that are loaded if loading the standard loading fails (or, smarter: use preprocessor to directly load the appropriate libraries).

Any changes to the handling of these libraries must be tested on Mac/Apple as well; if possible also with newer ARM based Macs.

Note: This is not a high-priority issue.

Add request endpoint that serves current position of the train in handler_driver (or handler_controller)

For executing systematic tests with MBT-Tools, it is advantageous to be able to query the position of a train.

handler_driver already implements train_position_is_at, but there is no way to query it from outside.
Proposal: Implement a onion/http-requestable method for retrieving the current position of a train in handler_monitor. handler_monitor should be the right place, as it is already implementing handler_get_train_state, which goes in a similar direction. This could also be implemented in handler_driver, but that'd imply that only the driver is allowed to query the position of their train.

Alternative: Include the current position of a train in the method handler_get_train_state of handler_monitor, which currently only says if the train is on the track, but not where.

If there already is a way to get the segment/block that the train is on, this issue can be closed.

Support Debugging of Dynamic Containers

Two options:

  • 1. Create a debug request handler that will dump the contents of dynamic container related data structures to the console.
  • 2. Create an automatic tracing thread that periodically writes the contents of dynamic container related data structures to a file.

Include more detailed reason for failure in engine upload process when compilation fails

File in question: server/src/handler_upload.c
Method: handler_upload_engine

The compilation of a train engine could fail in the C compilation OR the shared library compilation. This is not reflected in the log message:

dynlib_status status = dynlib_compile_scchart(filepath, engine_dir);
if (status == DYNLIB_COMPILE_SCCHARTS_C_ERR || status == DYNLIB_COMPILE_SHARED_SCCHARTS_ERR) {
	syslog_server(LOG_ERR, "Request: Upload - engine file %s could not be compiled", filepath);
	[....]
}

Request: Note the reason which compilation failed in the log message.

Verification on Engine Upload shall be integrated and configurable via Admin Client

(Feature Request)

The experimental feature for verification of train engines upon upload shall be integrated into the main branch.
With additional functionality: An Admin shall be able to enable or disable whether engines are verified upon upload. An Admin shall be able to do so via a web-interface akin to those existing for drivers and controllers. Furthermore, this shall be possible via the Python client as well.

I'll work on implementing this functionality. I'll do so on the verify_engine_models branch.

Incorrect driving direction on reverser

For automatic route driving, the driving direction is determined automatically.

When a train is on the reverser, this is not trivial. And there seems to be one scenario where we get the driving direction wrong.

Scenario where it works: Train is oriented/driving in a clockwise direction, on a route that has the destination signal 35a (on the reverser area). Train enters the reverser area from point 23. Is automatically stopped upon reaching the overlap at signal35a (T64). Now, selecting a new route from either signal35a or signal32 will result in the correct driving direction in automatic mode.

Scenario with the problem: Train is oriented/driving in a clockwise direction, on a route that has the destination signal 32 (on the reverser area). Train enters the reverser area coming from point 24. Is automatically stopped upon reaching the overlap at signal32 (T62). Now, selecting a new route from either signal35a or signal32 will result in the wrong (inversed) driving direction in automatic mode!
When the train reaches segment 62 (signal32), we can hear the click of the relais of the reverser.
If we drive the route to signal32 in manual mode and stop before reaching the overlap (and then manually release the route), the subsequent route direction is determined correctly.

So either this is...

  • linked to issue #120, and the reverser status is read incorrectly when/after the train touches segment 62; or
  • the code for determining direction is buggy in some other way.

Needs some more investigation on the implementation side.

Interlocking Container sometimes not released

When shutting down via the admin endpoint, the interlocking container is not released in some cases, potentially causing a segmentation fault on the next startup.
Missing in the log:

server: interlockerInstance0: Released container

Admin Train Release via Python Client leaves driver stuck

Procedure using the python cmdline client:

  1. driver grabs a train that is on the tracks
  2. admin force-releases that train
  3. driver tries to grab a new train -> "you can only grab one train!" (<- this is printed because the admin release does not reset the grab id that the python client has saved, thus it thinks the driver has already grabbed a train)
  4. driver tries to release their current train -> "System not running!" (<- server rejects, and python client prints out completely incorrect error message in all cases)

There should to be a way to properly reset the grab_id on the python client side, i.e., to synchronize with the server to some degree.

API formatting

Currently, the API returns results in a pure text-based manner, with some similar formats across different handler, but without a specification for it. This makes parsing a chore.
A common formatting standard (e.g., JSON) should help make parsing easier. However, which standard to choose and how to name its fields has to be discussed still.

Update include Paths for bidib

Libbidib now has the option to be installed in a include directory such as usr/local/include. This allows the swtbahn-cli cmake setup to be (more) portable. However, it does require a change in the include paths in .c and .h files. Bidib now has to be included with <bidib/bidib.h>, not <bidib.h>. This new schema is consistent with how we include onion.

I'll add the required changes to the Cmake setup and the includes.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.