modbus-sim 0.2.0__tar.gz → 0.2.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {modbus_sim-0.2.0 → modbus_sim-0.2.1}/CHANGELOG.md +5 -0
- {modbus_sim-0.2.0/src/modbus_sim.egg-info → modbus_sim-0.2.1}/PKG-INFO +57 -4
- {modbus_sim-0.2.0 → modbus_sim-0.2.1}/README.md +56 -3
- {modbus_sim-0.2.0 → modbus_sim-0.2.1}/pyproject.toml +1 -1
- {modbus_sim-0.2.0 → modbus_sim-0.2.1}/src/modbus_sim/__init__.py +1 -1
- {modbus_sim-0.2.0 → modbus_sim-0.2.1/src/modbus_sim.egg-info}/PKG-INFO +57 -4
- {modbus_sim-0.2.0 → modbus_sim-0.2.1}/LICENSE +0 -0
- {modbus_sim-0.2.0 → modbus_sim-0.2.1}/MANIFEST.in +0 -0
- {modbus_sim-0.2.0 → modbus_sim-0.2.1}/examples/plant.yaml +0 -0
- {modbus_sim-0.2.0 → modbus_sim-0.2.1}/examples/real-devices.yaml +0 -0
- {modbus_sim-0.2.0 → modbus_sim-0.2.1}/examples/test_example.py +0 -0
- {modbus_sim-0.2.0 → modbus_sim-0.2.1}/setup.cfg +0 -0
- {modbus_sim-0.2.0 → modbus_sim-0.2.1}/src/modbus_sim/__main__.py +0 -0
- {modbus_sim-0.2.0 → modbus_sim-0.2.1}/src/modbus_sim/bench.py +0 -0
- {modbus_sim-0.2.0 → modbus_sim-0.2.1}/src/modbus_sim/cli.py +0 -0
- {modbus_sim-0.2.0 → modbus_sim-0.2.1}/src/modbus_sim/client.py +0 -0
- {modbus_sim-0.2.0 → modbus_sim-0.2.1}/src/modbus_sim/control.py +0 -0
- {modbus_sim-0.2.0 → modbus_sim-0.2.1}/src/modbus_sim/datatypes.py +0 -0
- {modbus_sim-0.2.0 → modbus_sim-0.2.1}/src/modbus_sim/device.py +0 -0
- {modbus_sim-0.2.0 → modbus_sim-0.2.1}/src/modbus_sim/faults.py +0 -0
- {modbus_sim-0.2.0 → modbus_sim-0.2.1}/src/modbus_sim/frame.py +0 -0
- {modbus_sim-0.2.0 → modbus_sim-0.2.1}/src/modbus_sim/models.py +0 -0
- {modbus_sim-0.2.0 → modbus_sim-0.2.1}/src/modbus_sim/profile.py +0 -0
- {modbus_sim-0.2.0 → modbus_sim-0.2.1}/src/modbus_sim/profiles/eastron-sdm630.yaml +0 -0
- {modbus_sim-0.2.0 → modbus_sim-0.2.1}/src/modbus_sim/profiles/energy-meter.yaml +0 -0
- {modbus_sim-0.2.0 → modbus_sim-0.2.1}/src/modbus_sim/profiles/omron-e5cc.yaml +0 -0
- {modbus_sim-0.2.0 → modbus_sim-0.2.1}/src/modbus_sim/profiles/sunspec-inverter.yaml +0 -0
- {modbus_sim-0.2.0 → modbus_sim-0.2.1}/src/modbus_sim/profiles/temperature-controller.yaml +0 -0
- {modbus_sim-0.2.0 → modbus_sim-0.2.1}/src/modbus_sim/profiles/vfd.yaml +0 -0
- {modbus_sim-0.2.0 → modbus_sim-0.2.1}/src/modbus_sim/pytest_plugin.py +0 -0
- {modbus_sim-0.2.0 → modbus_sim-0.2.1}/src/modbus_sim/server.py +0 -0
- {modbus_sim-0.2.0 → modbus_sim-0.2.1}/src/modbus_sim/signals.py +0 -0
- {modbus_sim-0.2.0 → modbus_sim-0.2.1}/src/modbus_sim.egg-info/SOURCES.txt +0 -0
- {modbus_sim-0.2.0 → modbus_sim-0.2.1}/src/modbus_sim.egg-info/dependency_links.txt +0 -0
- {modbus_sim-0.2.0 → modbus_sim-0.2.1}/src/modbus_sim.egg-info/entry_points.txt +0 -0
- {modbus_sim-0.2.0 → modbus_sim-0.2.1}/src/modbus_sim.egg-info/requires.txt +0 -0
- {modbus_sim-0.2.0 → modbus_sim-0.2.1}/src/modbus_sim.egg-info/top_level.txt +0 -0
- {modbus_sim-0.2.0 → modbus_sim-0.2.1}/tests/conftest.py +0 -0
- {modbus_sim-0.2.0 → modbus_sim-0.2.1}/tests/test_cli.py +0 -0
- {modbus_sim-0.2.0 → modbus_sim-0.2.1}/tests/test_datatypes.py +0 -0
- {modbus_sim-0.2.0 → modbus_sim-0.2.1}/tests/test_device.py +0 -0
- {modbus_sim-0.2.0 → modbus_sim-0.2.1}/tests/test_device_profiles.py +0 -0
- {modbus_sim-0.2.0 → modbus_sim-0.2.1}/tests/test_frame.py +0 -0
- {modbus_sim-0.2.0 → modbus_sim-0.2.1}/tests/test_models.py +0 -0
- {modbus_sim-0.2.0 → modbus_sim-0.2.1}/tests/test_plugin.py +0 -0
- {modbus_sim-0.2.0 → modbus_sim-0.2.1}/tests/test_profile.py +0 -0
- {modbus_sim-0.2.0 → modbus_sim-0.2.1}/tests/test_server.py +0 -0
|
@@ -4,6 +4,11 @@ All notable changes to this project are documented here. The format follows
|
|
|
4
4
|
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/); versions follow
|
|
5
5
|
[Semantic Versioning](https://semver.org/).
|
|
6
6
|
|
|
7
|
+
## 0.2.1 - 2026-11-05
|
|
8
|
+
|
|
9
|
+
- Docker image on `ghcr.io/steitec/modbus-sim`: runs the profiles after real
|
|
10
|
+
devices on Modbus TCP, with the control channel for fault injection
|
|
11
|
+
|
|
7
12
|
## 0.2.0 - 2026-11-01
|
|
8
13
|
|
|
9
14
|
- Profiles after the published register maps of real devices:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: modbus-sim
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.1
|
|
4
4
|
Summary: Simulated Modbus devices with behaviour and fault injection: energy meter, temperature controller, VFD over Modbus TCP and RTU
|
|
5
5
|
Author: Ralf Steinert
|
|
6
6
|
License-Expression: MIT
|
|
@@ -42,9 +42,10 @@ Dynamic: license-file
|
|
|
42
42
|
# modbus-sim
|
|
43
43
|
|
|
44
44
|
[](https://github.com/steitec/modbus-sim/actions/workflows/ci.yml)
|
|
45
|
-
[](https://pypi.org/project/modbus-sim/)
|
|
46
|
+
[](https://pypi.org/project/modbus-sim/)
|
|
47
|
+
[](https://github.com/steitec/modbus-sim/blob/main/LICENSE)
|
|
48
|
+
[](https://modbus-sim.steitec.net)
|
|
48
49
|
|
|
49
50
|
Simulated Modbus devices that **behave**: an energy meter whose counters count,
|
|
50
51
|
a temperature controller that heats towards its setpoint, a frequency converter
|
|
@@ -57,6 +58,9 @@ Modbus TCP, RTU over TCP and RTU on a serial line or a virtual serial port, so
|
|
|
57
58
|
you can develop and test SCADA links, data loggers, gateways, Node-RED flows or
|
|
58
59
|
your own Modbus code without the hardware, also in CI.
|
|
59
60
|
|
|
61
|
+
Walkthroughs, CI recipes and troubleshooting are in the
|
|
62
|
+
[wiki](https://github.com/steitec/modbus-sim/wiki); this README is the reference.
|
|
63
|
+
|
|
60
64
|
```console
|
|
61
65
|
$ modbus-sim serve --bench examples/plant.yaml &
|
|
62
66
|
modbus-sim: 3 devices (units 1, 2, 3) on modbus tcp 127.0.0.1:5020, control on :5021
|
|
@@ -319,6 +323,55 @@ only, no authentication). It takes one JSON object per line:
|
|
|
319
323
|
set `null`); the CLI has the same as `modbus-sim set`, `get` and `list`.
|
|
320
324
|
`--no-control` turns the channel off.
|
|
321
325
|
|
|
326
|
+
## Docker
|
|
327
|
+
|
|
328
|
+
For clients that are not written in Python: the image runs the three profiles
|
|
329
|
+
after real devices behind one Modbus TCP port (`eastron-sdm630` as `meter` on
|
|
330
|
+
unit 1, `omron-e5cc` as `controller` on unit 2, `sunspec-inverter` as `inverter`
|
|
331
|
+
on unit 3).
|
|
332
|
+
|
|
333
|
+
```bash
|
|
334
|
+
docker run --rm --name sim -p 5020:5020 -p 127.0.0.1:5021:5021 ghcr.io/steitec/modbus-sim
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
The control channel has no authentication, hence `127.0.0.1:` in front of it.
|
|
338
|
+
It listens on all interfaces inside the container, so anything on the same
|
|
339
|
+
Docker network can reach it; use `serve ... --no-control` where that matters.
|
|
340
|
+
Inject a fault without installing anything, or send the
|
|
341
|
+
[JSON lines](#control-channel) to port 5021 from your own test code:
|
|
342
|
+
|
|
343
|
+
```bash
|
|
344
|
+
docker exec sim modbus-sim inject inverter grid_loss
|
|
345
|
+
docker exec sim modbus-sim clear inverter
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
Your client insists on port 502, or you have your own bench file:
|
|
349
|
+
|
|
350
|
+
```bash
|
|
351
|
+
docker run --rm -p 502:5020 ghcr.io/steitec/modbus-sim
|
|
352
|
+
docker run --rm -p 5020:5020 -v "$PWD/bench.yaml":/bench/bench.yaml ghcr.io/steitec/modbus-sim
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
Other arguments replace the default command. Keep `--host 0.0.0.0`, or the port
|
|
356
|
+
is only reachable from inside the container:
|
|
357
|
+
|
|
358
|
+
```bash
|
|
359
|
+
docker run --rm -p 5020:5020 ghcr.io/steitec/modbus-sim serve vfd --host 0.0.0.0 --rtu-over-tcp
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
As a service container in GitHub Actions:
|
|
363
|
+
|
|
364
|
+
```yaml
|
|
365
|
+
services:
|
|
366
|
+
modbus:
|
|
367
|
+
image: ghcr.io/steitec/modbus-sim
|
|
368
|
+
ports:
|
|
369
|
+
- 5020:5020
|
|
370
|
+
- 127.0.0.1:5021:5021
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
The image has no RTU on a serial port; use Modbus TCP or RTU over TCP.
|
|
374
|
+
|
|
322
375
|
## Python client
|
|
323
376
|
|
|
324
377
|
A minimal master is included, mainly for trying things out and for tests:
|
|
@@ -6,9 +6,10 @@
|
|
|
6
6
|
# modbus-sim
|
|
7
7
|
|
|
8
8
|
[](https://github.com/steitec/modbus-sim/actions/workflows/ci.yml)
|
|
9
|
-
[](https://pypi.org/project/modbus-sim/)
|
|
10
|
+
[](https://pypi.org/project/modbus-sim/)
|
|
11
|
+
[](https://github.com/steitec/modbus-sim/blob/main/LICENSE)
|
|
12
|
+
[](https://modbus-sim.steitec.net)
|
|
12
13
|
|
|
13
14
|
Simulated Modbus devices that **behave**: an energy meter whose counters count,
|
|
14
15
|
a temperature controller that heats towards its setpoint, a frequency converter
|
|
@@ -21,6 +22,9 @@ Modbus TCP, RTU over TCP and RTU on a serial line or a virtual serial port, so
|
|
|
21
22
|
you can develop and test SCADA links, data loggers, gateways, Node-RED flows or
|
|
22
23
|
your own Modbus code without the hardware, also in CI.
|
|
23
24
|
|
|
25
|
+
Walkthroughs, CI recipes and troubleshooting are in the
|
|
26
|
+
[wiki](https://github.com/steitec/modbus-sim/wiki); this README is the reference.
|
|
27
|
+
|
|
24
28
|
```console
|
|
25
29
|
$ modbus-sim serve --bench examples/plant.yaml &
|
|
26
30
|
modbus-sim: 3 devices (units 1, 2, 3) on modbus tcp 127.0.0.1:5020, control on :5021
|
|
@@ -283,6 +287,55 @@ only, no authentication). It takes one JSON object per line:
|
|
|
283
287
|
set `null`); the CLI has the same as `modbus-sim set`, `get` and `list`.
|
|
284
288
|
`--no-control` turns the channel off.
|
|
285
289
|
|
|
290
|
+
## Docker
|
|
291
|
+
|
|
292
|
+
For clients that are not written in Python: the image runs the three profiles
|
|
293
|
+
after real devices behind one Modbus TCP port (`eastron-sdm630` as `meter` on
|
|
294
|
+
unit 1, `omron-e5cc` as `controller` on unit 2, `sunspec-inverter` as `inverter`
|
|
295
|
+
on unit 3).
|
|
296
|
+
|
|
297
|
+
```bash
|
|
298
|
+
docker run --rm --name sim -p 5020:5020 -p 127.0.0.1:5021:5021 ghcr.io/steitec/modbus-sim
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
The control channel has no authentication, hence `127.0.0.1:` in front of it.
|
|
302
|
+
It listens on all interfaces inside the container, so anything on the same
|
|
303
|
+
Docker network can reach it; use `serve ... --no-control` where that matters.
|
|
304
|
+
Inject a fault without installing anything, or send the
|
|
305
|
+
[JSON lines](#control-channel) to port 5021 from your own test code:
|
|
306
|
+
|
|
307
|
+
```bash
|
|
308
|
+
docker exec sim modbus-sim inject inverter grid_loss
|
|
309
|
+
docker exec sim modbus-sim clear inverter
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
Your client insists on port 502, or you have your own bench file:
|
|
313
|
+
|
|
314
|
+
```bash
|
|
315
|
+
docker run --rm -p 502:5020 ghcr.io/steitec/modbus-sim
|
|
316
|
+
docker run --rm -p 5020:5020 -v "$PWD/bench.yaml":/bench/bench.yaml ghcr.io/steitec/modbus-sim
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
Other arguments replace the default command. Keep `--host 0.0.0.0`, or the port
|
|
320
|
+
is only reachable from inside the container:
|
|
321
|
+
|
|
322
|
+
```bash
|
|
323
|
+
docker run --rm -p 5020:5020 ghcr.io/steitec/modbus-sim serve vfd --host 0.0.0.0 --rtu-over-tcp
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
As a service container in GitHub Actions:
|
|
327
|
+
|
|
328
|
+
```yaml
|
|
329
|
+
services:
|
|
330
|
+
modbus:
|
|
331
|
+
image: ghcr.io/steitec/modbus-sim
|
|
332
|
+
ports:
|
|
333
|
+
- 5020:5020
|
|
334
|
+
- 127.0.0.1:5021:5021
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
The image has no RTU on a serial port; use Modbus TCP or RTU over TCP.
|
|
338
|
+
|
|
286
339
|
## Python client
|
|
287
340
|
|
|
288
341
|
A minimal master is included, mainly for trying things out and for tests:
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "modbus-sim"
|
|
7
|
-
version = "0.2.
|
|
7
|
+
version = "0.2.1"
|
|
8
8
|
description = "Simulated Modbus devices with behaviour and fault injection: energy meter, temperature controller, VFD over Modbus TCP and RTU"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = "MIT"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"""Simulated Modbus devices (energy meter, temperature controller, frequency converter)
|
|
2
2
|
with behaviour and fault injection, over Modbus TCP, RTU over TCP and serial RTU."""
|
|
3
|
-
__version__ = "0.2.
|
|
3
|
+
__version__ = "0.2.1"
|
|
4
4
|
|
|
5
5
|
from .bench import Bench, BenchError
|
|
6
6
|
from .client import ModbusClient, ModbusError
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: modbus-sim
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.1
|
|
4
4
|
Summary: Simulated Modbus devices with behaviour and fault injection: energy meter, temperature controller, VFD over Modbus TCP and RTU
|
|
5
5
|
Author: Ralf Steinert
|
|
6
6
|
License-Expression: MIT
|
|
@@ -42,9 +42,10 @@ Dynamic: license-file
|
|
|
42
42
|
# modbus-sim
|
|
43
43
|
|
|
44
44
|
[](https://github.com/steitec/modbus-sim/actions/workflows/ci.yml)
|
|
45
|
-
[](https://pypi.org/project/modbus-sim/)
|
|
46
|
+
[](https://pypi.org/project/modbus-sim/)
|
|
47
|
+
[](https://github.com/steitec/modbus-sim/blob/main/LICENSE)
|
|
48
|
+
[](https://modbus-sim.steitec.net)
|
|
48
49
|
|
|
49
50
|
Simulated Modbus devices that **behave**: an energy meter whose counters count,
|
|
50
51
|
a temperature controller that heats towards its setpoint, a frequency converter
|
|
@@ -57,6 +58,9 @@ Modbus TCP, RTU over TCP and RTU on a serial line or a virtual serial port, so
|
|
|
57
58
|
you can develop and test SCADA links, data loggers, gateways, Node-RED flows or
|
|
58
59
|
your own Modbus code without the hardware, also in CI.
|
|
59
60
|
|
|
61
|
+
Walkthroughs, CI recipes and troubleshooting are in the
|
|
62
|
+
[wiki](https://github.com/steitec/modbus-sim/wiki); this README is the reference.
|
|
63
|
+
|
|
60
64
|
```console
|
|
61
65
|
$ modbus-sim serve --bench examples/plant.yaml &
|
|
62
66
|
modbus-sim: 3 devices (units 1, 2, 3) on modbus tcp 127.0.0.1:5020, control on :5021
|
|
@@ -319,6 +323,55 @@ only, no authentication). It takes one JSON object per line:
|
|
|
319
323
|
set `null`); the CLI has the same as `modbus-sim set`, `get` and `list`.
|
|
320
324
|
`--no-control` turns the channel off.
|
|
321
325
|
|
|
326
|
+
## Docker
|
|
327
|
+
|
|
328
|
+
For clients that are not written in Python: the image runs the three profiles
|
|
329
|
+
after real devices behind one Modbus TCP port (`eastron-sdm630` as `meter` on
|
|
330
|
+
unit 1, `omron-e5cc` as `controller` on unit 2, `sunspec-inverter` as `inverter`
|
|
331
|
+
on unit 3).
|
|
332
|
+
|
|
333
|
+
```bash
|
|
334
|
+
docker run --rm --name sim -p 5020:5020 -p 127.0.0.1:5021:5021 ghcr.io/steitec/modbus-sim
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
The control channel has no authentication, hence `127.0.0.1:` in front of it.
|
|
338
|
+
It listens on all interfaces inside the container, so anything on the same
|
|
339
|
+
Docker network can reach it; use `serve ... --no-control` where that matters.
|
|
340
|
+
Inject a fault without installing anything, or send the
|
|
341
|
+
[JSON lines](#control-channel) to port 5021 from your own test code:
|
|
342
|
+
|
|
343
|
+
```bash
|
|
344
|
+
docker exec sim modbus-sim inject inverter grid_loss
|
|
345
|
+
docker exec sim modbus-sim clear inverter
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
Your client insists on port 502, or you have your own bench file:
|
|
349
|
+
|
|
350
|
+
```bash
|
|
351
|
+
docker run --rm -p 502:5020 ghcr.io/steitec/modbus-sim
|
|
352
|
+
docker run --rm -p 5020:5020 -v "$PWD/bench.yaml":/bench/bench.yaml ghcr.io/steitec/modbus-sim
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
Other arguments replace the default command. Keep `--host 0.0.0.0`, or the port
|
|
356
|
+
is only reachable from inside the container:
|
|
357
|
+
|
|
358
|
+
```bash
|
|
359
|
+
docker run --rm -p 5020:5020 ghcr.io/steitec/modbus-sim serve vfd --host 0.0.0.0 --rtu-over-tcp
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
As a service container in GitHub Actions:
|
|
363
|
+
|
|
364
|
+
```yaml
|
|
365
|
+
services:
|
|
366
|
+
modbus:
|
|
367
|
+
image: ghcr.io/steitec/modbus-sim
|
|
368
|
+
ports:
|
|
369
|
+
- 5020:5020
|
|
370
|
+
- 127.0.0.1:5021:5021
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
The image has no RTU on a serial port; use Modbus TCP or RTU over TCP.
|
|
374
|
+
|
|
322
375
|
## Python client
|
|
323
376
|
|
|
324
377
|
A minimal master is included, mainly for trying things out and for tests:
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|