Skip to main content

Read-only EtherNet/IP implicit connection bridge that captures PLC I/O data and publishes it to NATS

Project description

eip2nats - EtherNet/IP to NATS Bridge

Read-only bridge that opens an EtherNet/IP implicit (I/O) connection to a PLC, captures the T2O (Target-to-Originator) data stream and publishes every packet to a NATS subject. It does not write data to the PLC — it acts as a passive listener, similar to a sniffer.

All dependencies (libnats, libEIPScanner) are bundled in the wheel.

Features

  • Read-only: Captures PLC I/O data via implicit connection, no writes
  • Self-contained: Includes compiled libnats and libEIPScanner
  • Zero dependencies: No system library installation required
  • Device presets: Built-in assembly constants for known devices (RM75E, etc.)
  • High performance: Native C++ bindings with pybind11
  • Auto-reconnect: Recovers automatically from connection loss
  • Thread-safe: Safe handling of multiple connections

Installation

pip install eip2nats

Pre-built wheels are available on PyPI for Linux and Windows.

Building from Source

If a pre-built wheel is not available for your platform, you can build from source:

Linux:

./setup_project_linux.sh

Windows (PowerShell, requires Visual Studio Build Tools):

.\setup_project_windows.ps1

This automatically:

  1. Creates a virtual environment in venv/
  2. Installs Hatch and pybind11
  3. Compiles nats.c, EIPScanner and the Python binding
  4. Creates the wheel
  5. Installs the wheel in the venv

Usage

# Activate virtual environment
source venv/bin/activate    # Linux
.\venv\Scripts\Activate     # Windows PowerShell

# Run example
python examples/example_python.py

# Deactivate when done
deactivate

Basic Usage

import eip2nats

# Create bridge (using RM75E device presets)
bridge = eip2nats.EIPtoNATSBridge(
    "192.168.17.200",              # PLC IP address
    "nats://192.168.17.138:4222",  # NATS server
    "plc.data",                    # NATS subject/topic
    config_assembly=eip2nats.devices.RM75E.CONFIG_ASSEMBLY,
    o2t_assembly=eip2nats.devices.RM75E.O2T_ASSEMBLY,
    t2o_assembly=eip2nats.devices.RM75E.T2O_ASSEMBLY,
    t2o_size=100,
)

# Start
if bridge.start():
    import time
    print("Bridge running!")

    # Monitor
    while bridge.is_running():
        time.sleep(5)
        print(f"RX={bridge.get_received_count()}, "
              f"TX={bridge.get_published_count()}")

    # Stop
    bridge.stop()

More examples in examples/

Requirements

Linux:

  • Python 3.7+
  • git, cmake, make, g++, python3-venv

Windows:

  • Python 3.7+
  • git, cmake
  • Visual Studio Build Tools (cl.exe)

Development

See DEVELOPMENT.md for the full development guide (VSCode setup, debugging, workflows).

Create Release

hatch build

Manual Build (without setup script)

git clone https://github.com/kliskatek/eip2nats.git
cd eip2nats
pip install hatch pybind11

# Build dependencies
python scripts/build_nats.py
python scripts/build_eipscanner.py
python scripts/build_binding.py

# Create wheel
hatch build

Project Structure

eip2nats/
├── pyproject.toml                # Hatch configuration
├── hatch_build.py                # Hook for platform-specific wheel
├── README.md
├── DEVELOPMENT.md                # VSCode development guide
├── LICENSE                       # MIT
├── THIRD_PARTY_LICENSES          # nats.c and EIPScanner licenses
├── setup_project_linux.sh        # Automatic setup (Linux)
├── setup_project_windows.ps1     # Automatic setup (Windows)
├── src/
│   └── eip2nats/
│       ├── __init__.py           # Python package
│       ├── bindings.cpp          # pybind11 bindings
│       ├── EIPtoNATSBridge.h     # C++ header
│       ├── EIPtoNATSBridge.cpp   # C++ implementation
│       └── lib/                  # Compiled libraries (auto-generated)
│           ├── libnats.so / nats.dll
│           └── libEIPScanner.so / EIPScanner.dll
├── scripts/
│   ├── build_config.py           # Shared build configuration
│   ├── build_nats.py             # Builds nats.c
│   ├── build_eipscanner.py       # Builds EIPScanner
│   ├── build_binding.py          # Builds Python binding (.pyd/.so)
│   ├── build_example_cpp.py      # Builds C++ example
│   └── binding_CMakeLists.txt    # CMake template for binding (Windows)
├── examples/
│   ├── example_python.py         # Python example
│   └── example_cpp.cpp           # C++ example (debugging)
├── tests/
│   └── test_python.py            # Python unit tests
└── build/                        # Auto-generated, in .gitignore
    ├── dependencies/             # nats.c and EIPScanner clones
    └── example_cpp/              # Compiled C++ executable

How It Works

  1. Build scripts (scripts/):

    • build_nats.py: Clones and compiles nats.c -> libnats.so / nats.dll
    • build_eipscanner.py: Clones and compiles EIPScanner -> libEIPScanner.so / EIPScanner.dll
    • build_binding.py: Compiles the Python binding -> .so (Linux) / .pyd (Windows)
    • All copy binaries to src/eip2nats/lib/
  2. hatch build:

    • Packages the full src/eip2nats/ (code + binaries)
    • hatch_build.py forces platform-specific wheel tags
    • Linux: relative RPATH ($ORIGIN), Windows: os.add_dll_directory()
    • The wheel contains everything needed
  3. pip install:

    • Installs the wheel
    • Binaries end up in site-packages
    • Python loads libraries automatically
    • Works without system dependencies!

Advantages

vs System Libraries:

  • No sudo apt-get install required
  • No version conflicts
  • Portable across systems

vs Regular Wheels:

  • Includes all C/C++ dependencies
  • Single file to install
  • Works on systems without compilers

vs Docker:

  • Lighter (MBs vs GBs)
  • Direct Python integration
  • No Docker privileges required

API Reference

Class: EIPtoNATSBridge

bridge = eip2nats.EIPtoNATSBridge(
    plc_address: str,
    nats_url: str,
    nats_subject: str,
    use_binary_format: bool = True,
    config_assembly: int = 4,       # Configuration assembly instance
    o2t_assembly: int = 2,          # O2T data assembly instance
    t2o_assembly: int = 1,          # T2O data assembly instance
    t2o_size: int = 0,              # T2O connection size in bytes
)

Methods:

  • start() -> bool: Starts the bridge
  • stop() -> None: Stops the bridge
  • is_running() -> bool: Bridge status
  • get_received_count() -> int: Messages from PLC
  • get_published_count() -> int: Messages to NATS
  • get_reconnect_count() -> int: Automatic EIP reconnections

Device Presets: eip2nats.devices

Pre-defined assembly constants for known EIP devices:

eip2nats.devices.RM75E.CONFIG_ASSEMBLY  # 4
eip2nats.devices.RM75E.O2T_ASSEMBLY     # 2
eip2nats.devices.RM75E.T2O_ASSEMBLY     # 1

Troubleshooting

Error: "cannot open shared object file"

Even though the wheel includes the libraries, check RPATH:

ldd $(python -c "import eip2nats; print(eip2nats.__file__.replace('__init__.py', 'lib/eip2nats.*.so'))")

All dependencies should resolve locally.

Rebuild on Another System

git clone <repo>
cd eip2nats
python scripts/build_nats.py
python scripts/build_eipscanner.py
python scripts/build_binding.py
hatch build

Clean Builds

rm -rf build/ dist/ src/eip2nats/lib/

Changelog

v1.0.0 (2025)

  • Initial release
  • Self-contained wheel with nats.c and EIPScanner
  • Windows (MSVC) and Linux (GCC) support
  • Binary and JSON format support
  • Thread-safe operations

Contributing

  1. Fork the project
  2. Create a branch (git checkout -b feature/amazing)
  3. Commit changes (git commit -m 'Add amazing feature')
  4. Push (git push origin feature/amazing)
  5. Open a Pull Request

License

MIT License - see LICENSE file

Credits

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

eip2nats-1.1.0-cp313-cp313-win_amd64.whl (412.5 kB view details)

Uploaded CPython 3.13Windows x86-64

eip2nats-1.1.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl (1.6 MB view details)

Uploaded CPython 3.13manylinux: glibc 2.17+ x86-64

eip2nats-1.1.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl (1.5 MB view details)

Uploaded CPython 3.13manylinux: glibc 2.17+ ARM64

eip2nats-1.1.0-cp312-cp312-win_amd64.whl (412.5 kB view details)

Uploaded CPython 3.12Windows x86-64

eip2nats-1.1.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl (1.6 MB view details)

Uploaded CPython 3.12manylinux: glibc 2.17+ x86-64

eip2nats-1.1.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl (1.5 MB view details)

Uploaded CPython 3.12manylinux: glibc 2.17+ ARM64

eip2nats-1.1.0-cp311-cp311-win_amd64.whl (411.8 kB view details)

Uploaded CPython 3.11Windows x86-64

eip2nats-1.1.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl (1.6 MB view details)

Uploaded CPython 3.11manylinux: glibc 2.17+ x86-64

eip2nats-1.1.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl (1.5 MB view details)

Uploaded CPython 3.11manylinux: glibc 2.17+ ARM64

eip2nats-1.1.0-cp310-cp310-win_amd64.whl (410.8 kB view details)

Uploaded CPython 3.10Windows x86-64

eip2nats-1.1.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl (1.6 MB view details)

Uploaded CPython 3.10manylinux: glibc 2.17+ x86-64

eip2nats-1.1.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl (1.5 MB view details)

Uploaded CPython 3.10manylinux: glibc 2.17+ ARM64

eip2nats-1.1.0-cp39-cp39-win_amd64.whl (409.6 kB view details)

Uploaded CPython 3.9Windows x86-64

eip2nats-1.1.0-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.whl (1.6 MB view details)

Uploaded CPython 3.9manylinux: glibc 2.17+ x86-64

eip2nats-1.1.0-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.whl (1.5 MB view details)

Uploaded CPython 3.9manylinux: glibc 2.17+ ARM64

File details

Details for the file eip2nats-1.1.0-cp313-cp313-win_amd64.whl.

File metadata

  • Download URL: eip2nats-1.1.0-cp313-cp313-win_amd64.whl
  • Upload date:
  • Size: 412.5 kB
  • Tags: CPython 3.13, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: python-httpx/0.28.1

File hashes

Hashes for eip2nats-1.1.0-cp313-cp313-win_amd64.whl
Algorithm Hash digest
SHA256 8d82a10b2a413368cc89e45c78e531cd22152d94d9e1468d0c651cd46671fcfc
MD5 3dee45367a60497d42106db95aa0cd13
BLAKE2b-256 b2866a8f892f0095ed43bdf50fb0a04a6e4d770e92c8e49908dea7b62d23491d

See more details on using hashes here.

File details

Details for the file eip2nats-1.1.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl.

File metadata

File hashes

Hashes for eip2nats-1.1.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
Algorithm Hash digest
SHA256 81a051baa11fce637337437ef2f3a3f476ead15c4254c7ac66a118eef2df004a
MD5 94ef6c169b2cc1d11137d872886c22e7
BLAKE2b-256 886f7957a975e3ecdbd76bec3648e1c8f7162c2a478f5228c6158e9f9d2f8870

See more details on using hashes here.

File details

Details for the file eip2nats-1.1.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl.

File metadata

File hashes

Hashes for eip2nats-1.1.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl
Algorithm Hash digest
SHA256 f66b7b145e568c7d73fed7f86545299854ba4685b38a01e751637899e3ca94d0
MD5 e8e38dcafe6f43447ca9184535bee300
BLAKE2b-256 ca9b4ef5e6862182434d79be088f5b63870b98275bafd1487a2c0d0d86f07bc5

See more details on using hashes here.

File details

Details for the file eip2nats-1.1.0-cp312-cp312-win_amd64.whl.

File metadata

  • Download URL: eip2nats-1.1.0-cp312-cp312-win_amd64.whl
  • Upload date:
  • Size: 412.5 kB
  • Tags: CPython 3.12, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: python-httpx/0.28.1

File hashes

Hashes for eip2nats-1.1.0-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 2944abb0fa2c5d7d48ed9a5412a107f860a7a5361df145c82a0602e7d236b1df
MD5 c7f4f21fba97e5913a1b9375573d628b
BLAKE2b-256 fffbc9f012e88503a2963db22b0c48925eb4c56e160507b1463d5319e6b9382f

See more details on using hashes here.

File details

Details for the file eip2nats-1.1.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl.

File metadata

File hashes

Hashes for eip2nats-1.1.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
Algorithm Hash digest
SHA256 91c27923d3fe05267ca2d8b5b03e303b19b7f9585683c49341f0b10c114b9a22
MD5 2990690bb5b90016908987c77d35bf74
BLAKE2b-256 947ba542cbe1d81fcfdc921ab8311d5d9213e065ebcd6fa48b73494aecef07c5

See more details on using hashes here.

File details

Details for the file eip2nats-1.1.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl.

File metadata

File hashes

Hashes for eip2nats-1.1.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl
Algorithm Hash digest
SHA256 7a9d39776ae5ca6f077eeabf58bea7ef65595cb1864031b70aa065f463901845
MD5 17abd0b0fc62a533d2f181d3219aaaa8
BLAKE2b-256 1a75ec9cc12d3a93eda9ee07b25b2e99a7d84705244919dd601c345846f34466

See more details on using hashes here.

File details

Details for the file eip2nats-1.1.0-cp311-cp311-win_amd64.whl.

File metadata

  • Download URL: eip2nats-1.1.0-cp311-cp311-win_amd64.whl
  • Upload date:
  • Size: 411.8 kB
  • Tags: CPython 3.11, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: python-httpx/0.28.1

File hashes

Hashes for eip2nats-1.1.0-cp311-cp311-win_amd64.whl
Algorithm Hash digest
SHA256 ca6e30a2502d646b7147764c851ca9459d66ac0aa5c63b99196bc933eb1bb153
MD5 d072febdfeaeff2b840bc7812dd532cf
BLAKE2b-256 9372626000a825382fa0f5b75c636545f9952c9fb70833e5bc54012202c91915

See more details on using hashes here.

File details

Details for the file eip2nats-1.1.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl.

File metadata

File hashes

Hashes for eip2nats-1.1.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
Algorithm Hash digest
SHA256 71585306cd9782dfbc10c20929fe5e6197c10d250e5bb80d5509b07511c9b2e9
MD5 613eddf72431342f0bde0725dc16a9da
BLAKE2b-256 6951109259316f7c0e2bc92de0a0b74d721bf2a7f387f7f40402ad8a72a6dff5

See more details on using hashes here.

File details

Details for the file eip2nats-1.1.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl.

File metadata

File hashes

Hashes for eip2nats-1.1.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl
Algorithm Hash digest
SHA256 795249125fe670b69540253f38ed29af9a395741253ec7f0208c892001651e53
MD5 67256e8d4968dca779f00b611833a9f2
BLAKE2b-256 95995631451415a3da429929f79d773a734bbc35ae6b1c298b38ef7c564f32f7

See more details on using hashes here.

File details

Details for the file eip2nats-1.1.0-cp310-cp310-win_amd64.whl.

File metadata

  • Download URL: eip2nats-1.1.0-cp310-cp310-win_amd64.whl
  • Upload date:
  • Size: 410.8 kB
  • Tags: CPython 3.10, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: python-httpx/0.28.1

File hashes

Hashes for eip2nats-1.1.0-cp310-cp310-win_amd64.whl
Algorithm Hash digest
SHA256 6bf9841523ecced2396a8d46dabfe0816e29151c93c42c1b12cc574ffcca8fa5
MD5 3e14ad54fc177fd305d7bca147de7edc
BLAKE2b-256 e69bf986d9742d5c6cd6f5297ce459ac38a6c759d6d9c0fe54aec2e7d370c8ef

See more details on using hashes here.

File details

Details for the file eip2nats-1.1.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl.

File metadata

File hashes

Hashes for eip2nats-1.1.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
Algorithm Hash digest
SHA256 aa4d8aa8d32985f0f65490c38a7a6143694434dcb2e6763d460f24a74cdc5bd6
MD5 4b34d85c80965e9fe2679726d1cd6fc1
BLAKE2b-256 80126674908c84ed4651262f80f03933b730f02fe1a629b3565dad0cfa7ff28b

See more details on using hashes here.

File details

Details for the file eip2nats-1.1.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl.

File metadata

File hashes

Hashes for eip2nats-1.1.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl
Algorithm Hash digest
SHA256 b9c2ddb382631694db04052e3f4f88fddf4006ffd1e248e7f171be40d13c980b
MD5 42cb3c7de724ea73404c867af61caaa1
BLAKE2b-256 1a204f991c66d49c5b8dcfb656bf9f997bfbc5eab5b1b88bbf374c7363c7127b

See more details on using hashes here.

File details

Details for the file eip2nats-1.1.0-cp39-cp39-win_amd64.whl.

File metadata

  • Download URL: eip2nats-1.1.0-cp39-cp39-win_amd64.whl
  • Upload date:
  • Size: 409.6 kB
  • Tags: CPython 3.9, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: python-httpx/0.28.1

File hashes

Hashes for eip2nats-1.1.0-cp39-cp39-win_amd64.whl
Algorithm Hash digest
SHA256 23cd6ec07b607dfed0858405528caa6a84ec3f23d7c2ea9c2bed1781b425a913
MD5 993e136b6963e4a371602c63c27dd963
BLAKE2b-256 c1e1a5a1ab5c2525c08b5a2e79e93e374f69778f1fd40e2ce2a8f2f612f4a1b0

See more details on using hashes here.

File details

Details for the file eip2nats-1.1.0-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.whl.

File metadata

File hashes

Hashes for eip2nats-1.1.0-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
Algorithm Hash digest
SHA256 f23f38085ee7dec3d0778907946942a87e20e0179f4a23565b42432ecfc8db2a
MD5 4700861a9e1d3dd8834161a6cd5d9108
BLAKE2b-256 05497527dd8f15a3e27ae9adc2909736e82e18776ad962d35a1f968a8a45bcf4

See more details on using hashes here.

File details

Details for the file eip2nats-1.1.0-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.whl.

File metadata

File hashes

Hashes for eip2nats-1.1.0-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.whl
Algorithm Hash digest
SHA256 b50cdf7dc446b03cb7b4f86cc6d43ce1727334266f509d50fab4a9797ae82e14
MD5 22ff16420fd8648d9f211a28296a829d
BLAKE2b-256 a5a169a71f336110a7198489dd379633a640a85a1b329630b8f057615a4cf544

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page