Skip to main content
Pre-release

This release is a pre-release and may not be stable for production use.

modsim

modsim is a standalone Modbus simulator for device integration and testing. The v2 development source reads WoT Thing Models (TM), instantiates device descriptions (TD), and runs independent simulated devices on one Modbus TCP listener. Models, scenarios, the simulator and the client remain separate.

This README describes the v2 development branch. The published 2.0.0a1 preview predates the managed deployment commands shown below; do not assume an existing latest image or installed package contains the current source. Stable and preview releases are independent. See preview notes and release process.

Install from source

The v2 managed deployment commands are available in the development source; they are not included in the published 2.0.0a1 release. Clone the v2 branch and install its dependencies with uv:

git clone --branch v2 https://github.com/top-maker/modsim.git
cd modsim
uv sync --all-groups

Run locally

From the root directory, start the example deployment and check its status:

uv run modsim up -d
uv run modsim ps

The commands use examples/deployment.yaml by default. The example starts two virtual ADAM devices: Unit 1 exposes ADAM-5017UH raw inputs; Unit 2 exposes ADAM-6024 raw I/O with synthetic AO→AI and DO→DI loopback. These are simulation values, not verified physical measurements. Models, scenarios and source information are in modbus-models.

The deployment binds to all interfaces by default; set server.bind to 127.0.0.1 in examples/deployment.yaml to restrict a direct local run.

Useful commands for managing the deployment:

uv run modsim logs -f
uv run modsim up --dry-run
uv run modsim reset --device adam-5017uh
uv run modsim export
uv run modsim down

Export writes all TDs to output/ in the root directory by default; this directory is ignored by Git. Use -o FILE for one TD or --output-dir DIR to choose another directory.

Use -f FILE to select another deployment. In logs, -f follows output; use --file FILE to select the deployment. up runs in the foreground by default; -d runs it in the background. Ctrl+C stops a service started by a foreground up, but only detaches from an existing deployment or logs -f. Background services do not restart after a machine reboot unless managed by a process manager. Managed commands require POSIX (Linux/macOS/WSL); see managed deployments.

modsim export reads the current deployment file and does not require a running simulator. Use --running only when you need the last successfully applied configuration instead of current file contents. That option connects to the managed runtime in the same project environment; for Docker Compose, run it inside the container.

Run with Docker Compose

From the examples/ directory, build and start the current source:

docker compose up -d --build
docker compose logs -f

Compose publishes Modbus TCP only on host 127.0.0.1:5020 and restarts the container unless stopped. Each restart resets simulation state. TDs advertise 127.0.0.1 by default; configure the advertised host and port mapping when clients connect from another machine.

The deployment and model/scenario files are mounted from the repository. docker compose up -d starts the configured deployment; do not run modsim up again just to start it. After editing the mounted deployment file, apply the updated configuration to the running simulator with:

docker compose exec modsim python -m modsim up -f /app/examples/deployment.yaml -d

An unchanged device keeps its state; a changed device is replaced. Listener changes require a container restart. If you replace the deployment file itself, run docker compose up -d --force-recreate to refresh its bind mount. Export all running TDs directly into the host's examples/td/ directory. The Compose file maps the default output directory to that host directory. Run this from the examples/ directory:

docker compose exec modsim python -m modsim export --running

This creates one *.td.json file per device in examples/td/.

Stop the Compose deployment with docker compose down.

Example: test modpoll against modsim

This example uses modpoll v2 (modpoll==2.0.0a2) and the local modsim source. Export all TDs from the current deployment file. Run from the root directory; modsim does not need to be running:

uv run modsim export

In another terminal, from the root directory, read the exported TD:

modpoll --once --interval 0 --tcp 127.0.0.1 --tcp-port 5020 \
  --config ./output/adam-6024.td.json --export ./adam-6024-snapshot.json

If you need the last applied configuration from a Docker Compose deployment, use the Compose export command above and point modpoll to ./examples/td/adam-6024.td.json instead.

The TD selects Unit ID 2. On a fresh deployment, adam6024_raw reports AO0_RAW: 100 and AI0_RAW: 100; values may differ if previously written. The command reads the exported TD and connects to modsim on the host port.

Optional: write via MQTT

Start a temporary local broker and a continuously running modpoll process:

docker run --rm -d --name modpoll-demo-mqtt -p 127.0.0.1:1883:1883 \
  eclipse-mosquitto:2 mosquitto -c /mosquitto-no-auth.conf
modpoll --interval 0 --rate 1 --tcp 127.0.0.1 --tcp-port 5020 \
  --config ./adam-6024.td.json --mqtt-host 127.0.0.1 --mqtt-port 1883

After modpoll connects, publish a non-retained write to the topic named for the TD's title (adam6024_raw):

docker exec modpoll-demo-mqtt mosquitto_pub -h 127.0.0.1 \
  -t modpoll/adam6024_raw/set \
  -m '{"object_type":"holding_register","address":10,"value":432}'

Run the one-shot modpoll command again. AO0_RAW and loopback AI0_RAW should both read 432. This synthetic raw value does not verify the physical device's range or behavior. The example broker has no authentication and is published only on host loopback; port 1883 must be available.

Stop modpoll with Ctrl+C, stop the broker if used (docker stop modpoll-demo-mqtt), then stop modsim with uv run modsim down or stop the Compose deployment with docker compose down.

Models and scenarios

A deployment has a stable ID per device, a TM path, instance parameters and an optional scenario. TD IDs and Modbus Unit IDs must be unique. Scenarios define initial values, seeded generators and bindings; local Python behavior requires --allow-scripts. They do not duplicate the model's register mapping. See model configuration for the supported profile, codecs, constraints and behavior hooks.

For a single device without a managed deployment:

uv run python tools/fetch-models.py
uv run modsim --config examples/models/advantech/adam-5017uh/adam-5017uh.tm.json \
  --unit-id 1 --port 5020 \
  --scenario examples/models/advantech/adam-5017uh/simulation/adam-5017uh.sim.json

The single-device model runtime currently supports TCP. The unconfigured demo also supports TCP, UDP, TLS, RTU and ASCII; its datastore is shared by all Unit IDs. TLS loads certificates/pymodbus.crt and certificates/pymodbus.key from the working directory. See transport details.

The checked-in ADAM-6024 TD and its source hash can be checked with uv run python tools/generate-td.py --check; omit --check to regenerate.

Development

See CONTRIBUTING.md for the v2 workflow and checks. The repository keeps v1 and v2 release lines separate; no release is implied by a source change.

Pinned public model inputs

Device data and optional scenarios are maintained only in modbus-models. examples/model-source.yaml pins data release modbus-models-v1 to its full commit and individual SHA-256 hashes. Prepare examples with uv run python tools/fetch-models.py; this downloads verified local inputs to ignored examples/models/, never executes downloaded Python, and does not copy an interpreter. Re-run after updating the lock through a reviewed PR. The application keeps its independent modpoll-wot 0.2.0a2 dependency.

Single-device mode can read a fixed HTTPS TM URL directly. Optional scenarios remain local; scripts require explicit --allow-scripts. Managed deployments use Unix sockets and require POSIX; native Windows should use single-device foreground mode or WSL. Independent-wheel CI verifies single-device remote-TM startup, raw reads and process shutdown on Linux, macOS and native Windows. It does not certify managed commands on Windows or every OS/Python combination.

Metadata

Release files for modsim 2.0.0a2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for modsim 2.0.0a2
File Size Uploaded Provenance Actions
modsim-2.0.0a2.tar.gz 28.1 kB Without provenance Details for modsim-2.0.0a2.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for modsim 2.0.0a2
File Interpreter ABI Platform Actions
modsim-2.0.0a2-py3-none-any.whl Python 3 none any Details for modsim-2.0.0a2-py3-none-any.whl

Total release size: 61.4 kB

Release files / modsim-2.0.0a2.tar.gz

Download URL modsim-2.0.0a2.tar.gz
Size 28.1 kB
Tags Source
SHA-256 checksum
How to use checksums
5928a9501abedf3290936a2dff45b78ce6dddc7f9f08f7e148ac120bfe1176d4
BLAKE2b-256 checksum
How to use checksums
96792b2335fc929e403b279cc92fab245d69c9b09236bbf58c64e3f536f83e1d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.11.19 {"installer":{"name":"uv","version":"0.11.19","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"26.04","id":"resolute","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / modsim-2.0.0a2-py3-none-any.whl

Download URL modsim-2.0.0a2-py3-none-any.whl
Size 33.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
adb8cadfe2bd8fb80a4d776bb6aa1b34421c10fc792dbd8e49b1a61b87f350bb
BLAKE2b-256 checksum
How to use checksums
67d95a8187ba351a19596c4a9caa7fa73b36d02c925ebf0354e0ecddd55627dd
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.11.19 {"installer":{"name":"uv","version":"0.11.19","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"26.04","id":"resolute","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Security for modsim 2.0.0a2

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page