Metadata-Version: 2.4
Name: pyfactoryio
Version: 0.1.0
Summary: Factory IO Modbus Interface
Author: Developer
Classifier: Programming Language :: Python :: 3
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Requires-Python: >=3.8
Description-Content-Type: text/markdown
Requires-Dist: pyModbusTCP

# PyFactoryIO

PyFactoryIO is a Python library that provides a high-level, modular Modbus interface for interacting with [Factory I/O](https://factoryio.com/). It allows you to easily connect your Python control logic to Factory I/O simulations, abstracting away the low-level Modbus TCP communication and mapping digital/register inputs and outputs by name.

## Features

- **Easy Configuration:** Map Factory I/O sensors and actuators using descriptive names instead of Modbus addresses.
- **Event-Driven & Loop-Based Execution:** Provides decorators to run callbacks on state changes, or a continuous control loop for cyclic execution.
- **Auto-Mapping:** Automatically handles Modbus coils, discrete inputs, holding registers, and input registers.
- **Lightweight:** Built on top of `pyModbusTCP`.

## Installation

You can install `pyfactoryio` directly via pip:

```bash
pip install pyfactoryio
```

## Quick Start

### 1. Configure Factory I/O

Ensure Factory I/O is configured to use the **Modbus TCP Server** driver. By default, PyFactoryIO listens on `127.0.0.1` port `5020`.

### 2. Basic Example

Here is a simple example demonstrating how to read a sensor and trigger an actuator.

```python
from pyfactoryio import FactoryIOServer

# Define your input and output names in the order they appear in Factory I/O
DI_NAMES = ["Sensor_1", "Start_Button"]
DO_NAMES = ["Conveyor", "Warning_Light"]

# Initialize the server
server = FactoryIOServer(
    di_names=DI_NAMES,
    do_names=DO_NAMES
)

# Example 1: Event-driven callback
@server.on_change("Start_Button")
def on_start_pressed(value):
    if value:
        print("Start button pressed!")
        server.Conveyor = True
    else:
        print("Start button released!")
        server.Conveyor = False

# Example 2: Continuous control loop
def my_logic(srv):
    # This function is called continuously by run_loop
    if srv.Sensor_1:
        srv.Warning_Light = True
    else:
        srv.Warning_Light = False

if __name__ == "__main__":
    # Start the event loop (e.g., at 10Hz)
    server.run_loop(logic_func=my_logic, hz=10)
```

## Supported Variable Types

- **di_names:** Digital Inputs (Sensors, Buttons) - Read from Factory I/O via Coils.
- **do_names:** Digital Outputs (Conveyors, Lights) - Written to Factory I/O via Discrete Inputs.
- **ri_names:** Register Inputs (Analog Sensors) - Read from Factory I/O via Holding Registers.
- **ro_names:** Register Outputs (Analog Actuators) - Written to Factory I/O via Input Registers.

## License

This project is licensed under the MIT License.
