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_rm75e.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_rm75e.py    # Python example (RM75E)
│   ├── example_python_clipx.py   # Python example (ClipX)
│   └── 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.2.0-cp314-cp314-win_amd64.whl (431.1 kB view details)

Uploaded CPython 3.14Windows x86-64

eip2nats-1.2.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl (1.6 MB view details)

Uploaded CPython 3.14manylinux: glibc 2.17+ x86-64

eip2nats-1.2.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl (1.5 MB view details)

Uploaded CPython 3.14manylinux: glibc 2.17+ ARM64

eip2nats-1.2.0-cp313-cp313-win_amd64.whl (418.2 kB view details)

Uploaded CPython 3.13Windows x86-64

eip2nats-1.2.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.2.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.2.0-cp312-cp312-win_amd64.whl (418.3 kB view details)

Uploaded CPython 3.12Windows x86-64

eip2nats-1.2.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.2.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.2.0-cp311-cp311-win_amd64.whl (417.4 kB view details)

Uploaded CPython 3.11Windows x86-64

eip2nats-1.2.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.2.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.2.0-cp310-cp310-win_amd64.whl (416.3 kB view details)

Uploaded CPython 3.10Windows x86-64

eip2nats-1.2.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.2.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.2.0-cp39-cp39-win_amd64.whl (415.6 kB view details)

Uploaded CPython 3.9Windows x86-64

eip2nats-1.2.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.2.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.2.0-cp314-cp314-win_amd64.whl.

File metadata

  • Download URL: eip2nats-1.2.0-cp314-cp314-win_amd64.whl
  • Upload date:
  • Size: 431.1 kB
  • Tags: CPython 3.14, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: python-httpx/0.28.1

File hashes

Hashes for eip2nats-1.2.0-cp314-cp314-win_amd64.whl
Algorithm Hash digest
SHA256 00b7793a3544bd6f5f8dc03f2aca3227581bf4eb7a2af7dc38d99915e8dc5300
MD5 438b72b1525acd01f0accbd7b41dca25
BLAKE2b-256 5fa0acda18e0551de12151199b8356c3900d7850ea6aae00f0c0b690320da179

See more details on using hashes here.

File details

Details for the file eip2nats-1.2.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl.

File metadata

File hashes

Hashes for eip2nats-1.2.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
Algorithm Hash digest
SHA256 93c0fda0437c28b497d6004f5be7c72bf73755cfd03315ef80062f95bb82f44f
MD5 453a86727c5dbaf07da67595bdd1674d
BLAKE2b-256 38906a29249906531c88c788815788c2b1f86e86e6ab2488e72079ae8a64372b

See more details on using hashes here.

File details

Details for the file eip2nats-1.2.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl.

File metadata

File hashes

Hashes for eip2nats-1.2.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl
Algorithm Hash digest
SHA256 5fe9985dd83f96df5a1bad9a115fa8703ff229531554551dc83ef151db550147
MD5 4d15529cadffe2bd3f0d2f839c7dfaca
BLAKE2b-256 48a6c39a7b47f9ba99f963ca1625be6e8e12c047a12a4ba8f07a3752cdf7e9b2

See more details on using hashes here.

File details

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

File metadata

  • Download URL: eip2nats-1.2.0-cp313-cp313-win_amd64.whl
  • Upload date:
  • Size: 418.2 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.2.0-cp313-cp313-win_amd64.whl
Algorithm Hash digest
SHA256 f0acc15c91ff47fcbebb26146b275e144026a11ede9d5a4fa70e538f05bda47b
MD5 8564dea5e3eb929be6a5e1165687256f
BLAKE2b-256 9af36bca17b10c61845aa8094ff9dc7369cfe13165f70f1b7d62bb683f32ada7

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for eip2nats-1.2.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
Algorithm Hash digest
SHA256 fd9ecf2931b9f1e43651022d6328b9dbdee57bf8574bb92e1f2be7c981659079
MD5 934714553f76acf4c8c0c9337b84c65d
BLAKE2b-256 24e18df038e8d65499365d951926711306dd1cf3077049889f3008c39bcba0df

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for eip2nats-1.2.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl
Algorithm Hash digest
SHA256 6fc4f8d11d15e289c4a8c3d66a37faac25885455efb147d66b11fbbda2dd2a33
MD5 1052f8dfd18b42ef7d1b5b7aac47781c
BLAKE2b-256 c52b77995cc133590623d8b9ae3d70da2d56fb9516e6c6a14d8e70b55a3095a3

See more details on using hashes here.

File details

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

File metadata

  • Download URL: eip2nats-1.2.0-cp312-cp312-win_amd64.whl
  • Upload date:
  • Size: 418.3 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.2.0-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 ad9e6eede79c34606228831519fda6ba33eed676c473e4c3e2a60f8c9a8f12f7
MD5 5fa3b53ef2c6f4c4237fcd65f26a8b8b
BLAKE2b-256 a856e7408e9e22d1951fa925ef044e27a44d47b36e99229afb9af1fa8a960f7e

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for eip2nats-1.2.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
Algorithm Hash digest
SHA256 951b844b2c15568cc8b607a86051f2735ee206f356b1914852085d6e807b0dec
MD5 a8bc63f9c4fb4ff444faac15d03f6195
BLAKE2b-256 f31729ced7fe212a9bb3159b1d656b259533d297ba859f83a07cbd42e8848354

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for eip2nats-1.2.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl
Algorithm Hash digest
SHA256 618f6257872a6e9e73cf202a25e29f65b196f89f1afd2cb3883a0629dfd0c0b5
MD5 f217d1afc5080cd495ff39be3be8dc75
BLAKE2b-256 9d9b9d2d4138be48122b937a988ec0314ba4d84a0a955a665a0a17519922419e

See more details on using hashes here.

File details

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

File metadata

  • Download URL: eip2nats-1.2.0-cp311-cp311-win_amd64.whl
  • Upload date:
  • Size: 417.4 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.2.0-cp311-cp311-win_amd64.whl
Algorithm Hash digest
SHA256 2d2c4dfa3d089c8cb560d0143d5ea693778bba3d29c11af2f994e15cee0d9fb4
MD5 5a193c3488c334115cf6466244f021ed
BLAKE2b-256 6f7705f2cbffeae0ab75edcc0913900bdf2b73aa55efed374dca5c50b4841127

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for eip2nats-1.2.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
Algorithm Hash digest
SHA256 2866c4ee3dee8bf02e68146de4dc69f1ed431caf686e55ce5576935afc97c663
MD5 4c41984725c48c9a1a17f8b6220e2c89
BLAKE2b-256 e229cf48315184a1f99f7ffb9e45726c3a39088a3198d68b628b41f0c42fe548

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for eip2nats-1.2.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl
Algorithm Hash digest
SHA256 456151f8df4a9345d7b8fb64f87c79e3b487820a5a10131791ac8cd33490c24c
MD5 df83e8faa60a79c34fb32f17c0683ccc
BLAKE2b-256 233c7e47a3dfd430a56759da5f802d8950e85d81b51eb189f0ad4159d4c890e8

See more details on using hashes here.

File details

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

File metadata

  • Download URL: eip2nats-1.2.0-cp310-cp310-win_amd64.whl
  • Upload date:
  • Size: 416.3 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.2.0-cp310-cp310-win_amd64.whl
Algorithm Hash digest
SHA256 9bfc685d8d0b170fd28d151b4f5a89bd426152b1592a8ec9513120738ff66bec
MD5 315cbe6bb34f31f35cc7e58656705acd
BLAKE2b-256 273a7caf6c29808050055cd693f5152e66b64c9c7c2e34b606344a414a65434b

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for eip2nats-1.2.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
Algorithm Hash digest
SHA256 09e210e96dee16dc03e4cd58b55bfa850d1b4475f946c65ac324fc4d39d5e3aa
MD5 58c20ab7f3add107d088bc6ddf234b42
BLAKE2b-256 122346bae4275d2b80a13008a9174b1e6ffd919984a11eae1c9403f65ae986f4

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for eip2nats-1.2.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl
Algorithm Hash digest
SHA256 f17e3e9a05e7117ff0f441ff75a018074c38e0d53f2313e57478465ace64e499
MD5 f12a7aa6f942492dd3b64f79886da28c
BLAKE2b-256 b1a813eb640d280f1b49a6937d5422a182efff03281a3992f04a37a953824b87

See more details on using hashes here.

File details

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

File metadata

  • Download URL: eip2nats-1.2.0-cp39-cp39-win_amd64.whl
  • Upload date:
  • Size: 415.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.2.0-cp39-cp39-win_amd64.whl
Algorithm Hash digest
SHA256 69ce6f575f41e6717861e3140a33d8d5e77bb298496e10bf40d331084486085b
MD5 148c1cf84638ca63e5faaf5621acfddf
BLAKE2b-256 08d21c4b55ff44bb584e38497e46b8f531f63898a9cc25531610430d95861c67

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for eip2nats-1.2.0-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
Algorithm Hash digest
SHA256 4d175000fdf3a439dcd2dfacb98ab71dc52936b53e4b2890918234d4fb431887
MD5 9b4182e750d854b91896be0f51f24d84
BLAKE2b-256 bce659b00349b7f996b75c53c13120acca18cd7642b881c98984a03360a93dbb

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for eip2nats-1.2.0-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.whl
Algorithm Hash digest
SHA256 263f01bf70870633d62a7edc004793672004ee6421811a74879837a8128018f5
MD5 beee10013540b82d080bb7b54d117a56
BLAKE2b-256 3c6d2e684f7add1205e272ec190bdea43a53331e9cdeac4e48fe67bc91654f07

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