# matterlab_balances

`matterlab_balances` provides drivers for the balances used in the Matter Lab. It includes a serial driver for Sartorius balances and a network client for Mettler Toledo XPR/XSR balances, along with a small shared base interface for balance operations.

## Supported Devices

- `Balance`: shared abstract base class
- `SartoriusBalance`
- `MTXPRBalance`
- `MTXPRBalanceDoors`: door identifiers for the MT client

## Installation

Install the package:

```bash
pip install matterlab_balances
```

For development:

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

The package depends on:

- `matterlab_serial_device`
- `requests`
- `suds`
- `jinja2`
- `pprp`

## Quick Start

Example with a Sartorius balance:

```python
from matterlab_balances import SartoriusBalance

balance = SartoriusBalance(com_port="COM5")
print(balance.weigh(stable=False))
balance.tare(stable=False)
```

Example with an MT XPR/XSR balance:

```python
from matterlab_balances import MTXPRBalance
from matterlab_balances.mt_balance import WeighingCaptureMode

balance = MTXPRBalance(host="192.168.1.1", port=8002, password="password")
value, unit, stable = balance.get_weight(capture_mode=WeighingCaptureMode.IMMEDIATE)
print(value, unit, stable)
balance.close_session()
```

## Core API

The shared `Balance` interface exposes:

- `weigh(stable=True)`
- `tare(stable=True)`

Device-specific classes add their own helpers:

- `SartoriusBalance`: direct serial weighing and tare control
- `MTXPRBalance`: session handling, `get_weight(...)`, `tare(...)`, `zero(...)`, door control, and dosing-related operations

## Testing

### Simulation Tests

Simulation tests are the default validation layer and are safe for CI.

One-click run:

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

Direct pytest run:

```bash
pytest tests/test_base_balance.py tests/test_sartorius_sim.py tests/test_mt_sim.py
```

### Hardware Tests

Hardware tests are opt-in because real balances may not be reachable in every environment.

Available hardware test files:

- `tests/test_sartorius_real.py`
- `tests/test_mt_real.py`

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

Examples:

```bash
pytest tests/test_sartorius_real.py --run-real --com-port COM5
pytest tests/test_mt_real.py --run-real --host 192.168.1.1 --port 8002 --password password
```

You can also provide hardware configuration through environment variables:

- `BALANCE_COM_PORT`
- `BALANCE_HOST`
- `BALANCE_PORT`
- `BALANCE_PASSWORD`

## Examples

The `examples/` directory contains the recommended entry points:

- `examples/test_sim.py`: one-click simulation-only test runner
- `examples/real_devices.py`: readable examples for Sartorius and MT balances
- `examples/README.md`: short guide to the examples directory

## Development

Useful commands:

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

The default pytest configuration includes retries, timeouts, coverage output, and uses `src` as the import root for local development.

## Package Layout

```text
src/matterlab_balances/
  base_balance.py
  mt_balance.py
  sartorius_balance.py
tests/
examples/
```

## License

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