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.
Files changed (47) hide show
  1. {modbus_sim-0.2.0 → modbus_sim-0.2.1}/CHANGELOG.md +5 -0
  2. {modbus_sim-0.2.0/src/modbus_sim.egg-info → modbus_sim-0.2.1}/PKG-INFO +57 -4
  3. {modbus_sim-0.2.0 → modbus_sim-0.2.1}/README.md +56 -3
  4. {modbus_sim-0.2.0 → modbus_sim-0.2.1}/pyproject.toml +1 -1
  5. {modbus_sim-0.2.0 → modbus_sim-0.2.1}/src/modbus_sim/__init__.py +1 -1
  6. {modbus_sim-0.2.0 → modbus_sim-0.2.1/src/modbus_sim.egg-info}/PKG-INFO +57 -4
  7. {modbus_sim-0.2.0 → modbus_sim-0.2.1}/LICENSE +0 -0
  8. {modbus_sim-0.2.0 → modbus_sim-0.2.1}/MANIFEST.in +0 -0
  9. {modbus_sim-0.2.0 → modbus_sim-0.2.1}/examples/plant.yaml +0 -0
  10. {modbus_sim-0.2.0 → modbus_sim-0.2.1}/examples/real-devices.yaml +0 -0
  11. {modbus_sim-0.2.0 → modbus_sim-0.2.1}/examples/test_example.py +0 -0
  12. {modbus_sim-0.2.0 → modbus_sim-0.2.1}/setup.cfg +0 -0
  13. {modbus_sim-0.2.0 → modbus_sim-0.2.1}/src/modbus_sim/__main__.py +0 -0
  14. {modbus_sim-0.2.0 → modbus_sim-0.2.1}/src/modbus_sim/bench.py +0 -0
  15. {modbus_sim-0.2.0 → modbus_sim-0.2.1}/src/modbus_sim/cli.py +0 -0
  16. {modbus_sim-0.2.0 → modbus_sim-0.2.1}/src/modbus_sim/client.py +0 -0
  17. {modbus_sim-0.2.0 → modbus_sim-0.2.1}/src/modbus_sim/control.py +0 -0
  18. {modbus_sim-0.2.0 → modbus_sim-0.2.1}/src/modbus_sim/datatypes.py +0 -0
  19. {modbus_sim-0.2.0 → modbus_sim-0.2.1}/src/modbus_sim/device.py +0 -0
  20. {modbus_sim-0.2.0 → modbus_sim-0.2.1}/src/modbus_sim/faults.py +0 -0
  21. {modbus_sim-0.2.0 → modbus_sim-0.2.1}/src/modbus_sim/frame.py +0 -0
  22. {modbus_sim-0.2.0 → modbus_sim-0.2.1}/src/modbus_sim/models.py +0 -0
  23. {modbus_sim-0.2.0 → modbus_sim-0.2.1}/src/modbus_sim/profile.py +0 -0
  24. {modbus_sim-0.2.0 → modbus_sim-0.2.1}/src/modbus_sim/profiles/eastron-sdm630.yaml +0 -0
  25. {modbus_sim-0.2.0 → modbus_sim-0.2.1}/src/modbus_sim/profiles/energy-meter.yaml +0 -0
  26. {modbus_sim-0.2.0 → modbus_sim-0.2.1}/src/modbus_sim/profiles/omron-e5cc.yaml +0 -0
  27. {modbus_sim-0.2.0 → modbus_sim-0.2.1}/src/modbus_sim/profiles/sunspec-inverter.yaml +0 -0
  28. {modbus_sim-0.2.0 → modbus_sim-0.2.1}/src/modbus_sim/profiles/temperature-controller.yaml +0 -0
  29. {modbus_sim-0.2.0 → modbus_sim-0.2.1}/src/modbus_sim/profiles/vfd.yaml +0 -0
  30. {modbus_sim-0.2.0 → modbus_sim-0.2.1}/src/modbus_sim/pytest_plugin.py +0 -0
  31. {modbus_sim-0.2.0 → modbus_sim-0.2.1}/src/modbus_sim/server.py +0 -0
  32. {modbus_sim-0.2.0 → modbus_sim-0.2.1}/src/modbus_sim/signals.py +0 -0
  33. {modbus_sim-0.2.0 → modbus_sim-0.2.1}/src/modbus_sim.egg-info/SOURCES.txt +0 -0
  34. {modbus_sim-0.2.0 → modbus_sim-0.2.1}/src/modbus_sim.egg-info/dependency_links.txt +0 -0
  35. {modbus_sim-0.2.0 → modbus_sim-0.2.1}/src/modbus_sim.egg-info/entry_points.txt +0 -0
  36. {modbus_sim-0.2.0 → modbus_sim-0.2.1}/src/modbus_sim.egg-info/requires.txt +0 -0
  37. {modbus_sim-0.2.0 → modbus_sim-0.2.1}/src/modbus_sim.egg-info/top_level.txt +0 -0
  38. {modbus_sim-0.2.0 → modbus_sim-0.2.1}/tests/conftest.py +0 -0
  39. {modbus_sim-0.2.0 → modbus_sim-0.2.1}/tests/test_cli.py +0 -0
  40. {modbus_sim-0.2.0 → modbus_sim-0.2.1}/tests/test_datatypes.py +0 -0
  41. {modbus_sim-0.2.0 → modbus_sim-0.2.1}/tests/test_device.py +0 -0
  42. {modbus_sim-0.2.0 → modbus_sim-0.2.1}/tests/test_device_profiles.py +0 -0
  43. {modbus_sim-0.2.0 → modbus_sim-0.2.1}/tests/test_frame.py +0 -0
  44. {modbus_sim-0.2.0 → modbus_sim-0.2.1}/tests/test_models.py +0 -0
  45. {modbus_sim-0.2.0 → modbus_sim-0.2.1}/tests/test_plugin.py +0 -0
  46. {modbus_sim-0.2.0 → modbus_sim-0.2.1}/tests/test_profile.py +0 -0
  47. {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.0
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
  [![CI](https://github.com/steitec/modbus-sim/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/steitec/modbus-sim/actions/workflows/ci.yml)
45
- [![PyPI](https://img.shields.io/pypi/v/modbus-sim?v=0.2.0)](https://pypi.org/project/modbus-sim/)
46
- [![Python](https://img.shields.io/pypi/pyversions/modbus-sim?v=0.2.0)](https://pypi.org/project/modbus-sim/)
47
- [![License](https://img.shields.io/pypi/l/modbus-sim?v=0.2.0)](https://github.com/steitec/modbus-sim/blob/main/LICENSE)
45
+ [![PyPI](https://img.shields.io/pypi/v/modbus-sim?v=0.2.1)](https://pypi.org/project/modbus-sim/)
46
+ [![Python](https://img.shields.io/pypi/pyversions/modbus-sim?v=0.2.1)](https://pypi.org/project/modbus-sim/)
47
+ [![License](https://img.shields.io/pypi/l/modbus-sim?v=0.2.1)](https://github.com/steitec/modbus-sim/blob/main/LICENSE)
48
+ [![Demo](https://img.shields.io/badge/demo-live%20in%20your%20browser-2ea44f)](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
  [![CI](https://github.com/steitec/modbus-sim/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/steitec/modbus-sim/actions/workflows/ci.yml)
9
- [![PyPI](https://img.shields.io/pypi/v/modbus-sim?v=0.2.0)](https://pypi.org/project/modbus-sim/)
10
- [![Python](https://img.shields.io/pypi/pyversions/modbus-sim?v=0.2.0)](https://pypi.org/project/modbus-sim/)
11
- [![License](https://img.shields.io/pypi/l/modbus-sim?v=0.2.0)](https://github.com/steitec/modbus-sim/blob/main/LICENSE)
9
+ [![PyPI](https://img.shields.io/pypi/v/modbus-sim?v=0.2.1)](https://pypi.org/project/modbus-sim/)
10
+ [![Python](https://img.shields.io/pypi/pyversions/modbus-sim?v=0.2.1)](https://pypi.org/project/modbus-sim/)
11
+ [![License](https://img.shields.io/pypi/l/modbus-sim?v=0.2.1)](https://github.com/steitec/modbus-sim/blob/main/LICENSE)
12
+ [![Demo](https://img.shields.io/badge/demo-live%20in%20your%20browser-2ea44f)](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.0"
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.0"
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.0
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
  [![CI](https://github.com/steitec/modbus-sim/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/steitec/modbus-sim/actions/workflows/ci.yml)
45
- [![PyPI](https://img.shields.io/pypi/v/modbus-sim?v=0.2.0)](https://pypi.org/project/modbus-sim/)
46
- [![Python](https://img.shields.io/pypi/pyversions/modbus-sim?v=0.2.0)](https://pypi.org/project/modbus-sim/)
47
- [![License](https://img.shields.io/pypi/l/modbus-sim?v=0.2.0)](https://github.com/steitec/modbus-sim/blob/main/LICENSE)
45
+ [![PyPI](https://img.shields.io/pypi/v/modbus-sim?v=0.2.1)](https://pypi.org/project/modbus-sim/)
46
+ [![Python](https://img.shields.io/pypi/pyversions/modbus-sim?v=0.2.1)](https://pypi.org/project/modbus-sim/)
47
+ [![License](https://img.shields.io/pypi/l/modbus-sim?v=0.2.1)](https://github.com/steitec/modbus-sim/blob/main/LICENSE)
48
+ [![Demo](https://img.shields.io/badge/demo-live%20in%20your%20browser-2ea44f)](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