Skip to content

Files

Latest commit

d29e3a5 · Feb 28, 2024

History

History
248 lines (186 loc) · 12 KB

README.md

File metadata and controls

248 lines (186 loc) · 12 KB

Pymodbus REPL Server

Pymodbus REPL server helps to quickly start an asynchronous server from the command line.

Support both Modbus TCP and Modbus RTU server.

Some features offered are


  1. Runs a reactive server in REPL and NON REPL mode.
  2. Exposes REST API's to manipulate the behaviour of the server in non REPL mode.
  3. Ability to manipulate the out-going response dynamically (either via REPL console or via REST API request).
  4. Ability to delay the out-going response dynamically (either via REPL console or via REST API request).
  5. Auto revert to normal response after pre-defined number of manipulated responses.

Installation

Install pymodbus with the required dependencies

pip install pymodbus[repl]

Usage

Invoke REPL server with pymodbus.server run command.

 ✗ pymodbus.server --help

 Usage: pymodbus.server [OPTIONS] COMMAND [ARGS]...

 Reactive Modbus server

╭─ Options ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ --host                                    TEXT     Host address [default: localhost]                                       │
│ --web-port                                INTEGER  Web app port [default: 8080]                                            │
│                       -b                           Support broadcast messages                                              │
│ --repl                    --no-repl                Enable/Disable repl for server [default: repl]                          │
│ --verbose                 --no-verbose             Run with debug logs enabled for pymodbus [default: no-verbose]          │
│ --install-completion                               Install completion for the current shell.                               │
│ --show-completion                                  Show completion for the current shell, to copy it or customize the      │
│                                                    installation.                                                           │
│ --help                                             Show this message and exit.                                             │
╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
╭─ Commands ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ run              Run Reactive Modbus server.                                                                               │
╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
✗ pymodbus.server run --help

 Usage: pymodbus.server run [OPTIONS]

 Run Reactive Modbus server.
 Exposing REST endpoint for response manipulation.

╭─ Options ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ --modbus-server  -s      TEXT     Modbus Server [default: ModbusServerTypes.tcp]                                           │
│ --framer         -f      TEXT     Modbus framer to use [default: ModbusFramerTypes.socket]                                 │
│ --modbus-port    -p      INTEGER  Modbus port [default: 5020]                                                              │
│ --slave-id       -u      INTEGER  Supported Modbus slave id's [default: None]                                              │
│ --modbus-config-path     PATH     Path to additional modbus server config [default: None]                                  │
│ --random         -r      INTEGER  Randomize every `r` reads. 0=never, 1=always,2=every-second-read, and so on. Applicable  │
│                                   IR and DI.                                                                               │
│                                   [default: 0]                                                                             │
│ --help                            Show this message and exit.                                                              │
╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯

Pymodbus Server REPL mode

The REPL server comes with auto-completion and can be installed for the supported shell with pymodbus.server --install-completion <shell>. Don't forget to restart the terminal for the auto-completion to kick-in. Use TAB key to show auto-completion.

Server in Action

Example usage.

❯ pymodbus.server run

__________                          .______.                    _________
\______   \___.__. _____   ____   __| _/\_ |__  __ __  ______  /   _____/ ______________  __ ___________
 |     ___<   |  |/     \ /  _ \ / __ |  | __ \|  |  \/  ___/  \_____  \_/ __ \_  __ \  \/ // __ \_  __ \\
 |    |    \___  |  Y Y  (  <_> ) /_/ |  | \_\ \  |  /\___ \   /        \  ___/|  | \/\   /\  ___/|  | \/
 |____|    / ____|__|_|  /\____/\____ |  |___  /____//____  > /_______  /\___  >__|    \_/  \___  >__|
           \/          \/            \/      \/           \/          \/     \/                 \/
                                                                                                v2.0.2-Pymodbus3.7.0dev


SERVER > help
Available commands:
clear                                        Clears screen
config                                       Print server config
exit                                         Exits REPL Server
manipulator                                  Manipulate response from server.
Usage: manipulator response_type=|normal|error|delayed|empty|stray
	Additional parameters
		error_code=<int>
		delay_by=<in seconds>
		clear_after=<clear after n messages int>
		data_len=<length of stray data (int)>

	Example usage:
	1. Send error response 3 for 4 requests
	   manipulator response_type=error error_code=3 clear_after=4
	2. Delay outgoing response by 5 seconds indefinitely
	   manipulator response_type=delayed delay_by=5
	3. Send empty response
	   manipulator response_type=empty
	4. Send stray response of length 12 and revert to normal after 2 responses
	   manipulator response_type=stray data_len=11 clear_after=2
	5. To disable response manipulation
	   manipulator response_type=normal

### View current server config
SERVER > config
Server Configs:
response_type                                normal
delay_by                                     0
error_code                                   2
clear_after                                  5

#### Manipulate response to return error code 3 and clear error after 3 requests
SERVER > manipulator response_type error error_code 3 clear_after 3

### Config after manipulation is set.

SERVER > config
Server Configs:
response_type                                error
error_code                                   3
clear_after                                  3
SERVER > 2024-02-28 12:20:55,573 ERROR logging:115 Unknown exception "cannot unpack non-iterable ReadInputRegistersResponse object" on stream server forcing disconnect

#### Config after 3 requests
SERVER >
SERVER > config
Server Configs:
response_type                                normal
delay_by                                     0
error_code                                   2
clear_after                                  5

Pymodbus Server REPL

Pymodbus Server Non REPL Mode

To run the Reactive server in the non-repl mode use --no-repl flag while starting the server. The server responses can still be manipulated with REST API calls.

pymodbus.server --no-repl --verbose run  --modbus-server tcp --framer socket --slave-id 1 --slave-id 4 --random 2 --modbus-port 5020
2022-10-27 13:32:56,062 MainThread      INFO     main           :246      Modbus server started

Reactive Modbus Server started.
======== Running on http://localhost:8080 ========

===========================================================================
Example Usage:
curl -X POST http://localhost:8080 -d "{"response_type": "error", "error_code": 4}"
===========================================================================

REST API

The server response can be manipulated by doing a POST request on the web-server running http://<host>:<port>. The values for host and port can be modified with --host and --web-port params while starting the server. The default values are localhost and 8080

pymodbus.server --host <host-ip> --web-port <new-port> run .....

The payload for the POST requests is

{
    "response_type": "normal",  # normal, error, delayed, empty, stray
    "delay_by": <int>,
    "data_len": <int>,
    "error_code": <int>,
    "clear_after": <int>,  # request count
}
  • response_type : Response expected from the server.
    • normal : Normal response, no errors
    • error: Return error responses , requires additional error_code field for the modbus error code to be returned.
      • error_code: Error code to return, possible values are
      • 0x01  # IllegalFunction
        0x02  # IllegalAddress
        0x03  # IllegalValue
        0x04  # SlaveFailure
        0x05  # Acknowledge
        0x06  # SlaveBusy
        0x08  # MemoryParityError
        0x0A  # GatewayPathUnavailable
        0x0B  # GatewayNoResponse
        
        
    • delayed: Responses are delayed by the time specified with delay_by field.
      • delay_by: Delay the response by seconds (float).
    • empty: Returns an empty response or no response
    • stray: Returns stray/junk response with length specified with data_len field.
      • data_len: Length of the stray_data (int)
    • clear_after: Clears the error responses after requests (int)

EXAMPLES

Return exception response 0x02 Illegal Address and clear after 5 requests

curl -X POST http://localhost:8080 -d '{"response_type": "error", "error_code": 2, "clear_after": 5}'

Return Empty response

curl -X POST http://localhost:8080 -d '{"response_type": "empty"}'

Return Stray response of length 25bytes

curl -X POST http://localhost:8080 -d '{"response_type": "stray", "data_len": 25}'

Delay responses by 3 seconds

curl -X POST http://localhost:8080 -d '{"response_type": "delayed", "delay_by": 3}'

Revert to normal responses

curl -X POST http://localhost:8080 -d '{"response_type": "normal"}'

TODO

  • Add REST Api endpoint to view current manipulator config.