# matterlab_valves

`matterlab_valves` is a Python package for controlling several valve controllers used in the Matter Lab. It provides a shared switching-valve interface plus device-specific drivers built on top of `matterlab_serial_device`.

## Supported Devices

- `JKem4in1Valve`: classic JKem 4-in-1 serial valve controller
- `JKemNewValve`: newer JKem serial valve protocol
- `ValcoSelectionValve`: Valco selection valves
- `RunzeSelectionValve`: Runze RS485 selection valves
- `SwitchingValve`: shared abstract base class for valve-like devices

## Installation

Install the package:

```bash
pip install matterlab_valves
```

For development:

```bash
pip install -e .[dev]
```

The package depends on `matterlab_serial_device`, which is installed automatically as a runtime dependency.

## Quick Start

Example with a Valco valve:

```python
from matterlab_valves import ValcoSelectionValve

valve = ValcoSelectionValve(
    com_port="COM5",
    num_port=10,
    ports={"home": 1, "collect": 2},
)

print("Current port:", valve.port)
valve.switch_port("collect")
print("Current port:", valve.port)
```

All valve implementations expose a `port` property for reading and setting the active position. If you provide a `ports` mapping, you can use human-readable names with `switch_port(...)`.

## Device Overview

### JKem 4-in-1

Required parameters:

- `com_port`
- `valve_num`

Example:

```python
from matterlab_valves import JKem4in1Valve

valve = JKem4in1Valve(
    com_port="COM11",
    valve_num=3,
    ports={"load": 1, "inject": 2},
)

valve.port = 1
valve.switch_port("inject")
```

### JKem New

Required parameters:

- `com_port`
- `valve_num`

Example:

```python
from matterlab_valves import JKemNewValve

valve = JKemNewValve(
    com_port="COM11",
    valve_num=1,
    ports={"load": 1, "inject": 2},
)

print(valve.port)
```

### Valco Selection Valve

Required parameters:

- `com_port`
- `num_port`

Example:

```python
from matterlab_valves import ValcoSelectionValve

valve = ValcoSelectionValve(
    com_port="COM5",
    num_port=10,
    ports={"home": 1, "collect": 2},
)

valve.port = 2
valve.switch_port("home")
```

### Runze Selection Valve

Required parameters:

- `com_port`
- `address`
- `num_port`

Example:

```python
from matterlab_valves import RunzeSelectionValve

valve = RunzeSelectionValve(
    com_port="COM3",
    address=0,
    num_port=10,
    ports={"home": 1, "collect": 2},
)

valve.port = 2
valve.switch_port("home")
```

## Examples

Readable usage examples live in `examples/`:

- `examples/test_sim.py`: one-click simulation-only test runner
- `examples/real_devices.py`: human-readable hardware usage examples
- `examples/README.md`: short guide to the examples directory

Run the simulation suite with:

```bash
python examples/test_sim.py
```

## Testing

### Simulation Tests

The simulation suite is the default validation layer and is safe for CI.

One-click run:

```bash
python examples/test_sim.py
```

Direct pytest run:

```bash
pytest tests/test_jkem_4in1_sim.py tests/test_jkem_new_sim.py tests/test_valco_selection_sim.py tests/test_runze_selection_sim.py tests/test_switching_valve.py
```

### Hardware Tests

Hardware tests are present for all supported valve families, but they are opt-in because physical devices may not be connected in every environment.

Available hardware test files:

- `tests/test_jkem_4in1_real.py`
- `tests/test_jkem_new_real.py`
- `tests/test_valco_selection_real.py`
- `tests/test_runze_selection_real.py`

They are marked with `@pytest.mark.real` and are skipped unless `--run-real` is provided.

Example:

```bash
pytest tests/test_jkem_4in1_real.py --run-real --com-port COM11 --valve-num 3
```

Hardware configuration may be supplied through CLI flags or environment variables:

- `--com-port` or `VALVE_COM_PORT`
- `--num-port` or `VALVE_NUM_PORT`
- `--address` or `VALVE_ADDRESS`
- `--valve-num` or `VALVE_VALVE_NUM`

## Development

Useful commands:

```bash
pytest
ruff check .
ruff format .
```

The default pytest configuration includes timeout, rerun, and coverage options from `pyproject.toml`.

## Package Layout

```text
src/matterlab_valves/
  base_valve.py
  jkem_4in1_valve.py
  jkem_new.py
  runze_valve.py
  valco_selection_valve.py
tests/
examples/
```

## License

This project is distributed under the MIT License. See `LICENSE` for details.
