Metadata-Version: 2.4
Name: pyecobulles
Version: 0.2.0
Summary: Async Python client for the Ecobulles cloud API
Author-email: Julien <jul-fls@users.noreply.github.com>
License-Expression: Apache-2.0
Project-URL: Homepage, https://github.com/jul-fls/pyecobulles
Project-URL: Issues, https://github.com/jul-fls/pyecobulles/issues
Project-URL: Repository, https://github.com/jul-fls/pyecobulles
Classifier: Development Status :: 3 - Alpha
Classifier: Framework :: AsyncIO
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Typing :: Typed
Requires-Python: >=3.12
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: aiohttp>=3.9
Dynamic: license-file

# pyecobulles

[![CI](https://github.com/jul-fls/pyecobulles/actions/workflows/ci.yml/badge.svg)](https://github.com/jul-fls/pyecobulles/actions/workflows/ci.yml)
[![codecov](https://codecov.io/gh/jul-fls/pyecobulles/branch/master/graph/badge.svg)](https://codecov.io/gh/jul-fls/pyecobulles)
[![PyPI](https://img.shields.io/pypi/v/pyecobulles.svg)](https://pypi.org/project/pyecobulles/)

`pyecobulles` is an unofficial async Python client for the [Ecobulles customer portal](https://portail.ecobulles.com/login). Ecobulles produces CO₂ water treatment systems that reduce limescale without salt. A connected box reports water use, device status, alerts and its latest sensor readings through the portal.

Version 0.2 uses the new customer portal. Ecobulles announced that its older mobile application will be discontinued. The client uses the same account email and password as the portal; it does not store credentials on disk.

## Install

```bash
pip install pyecobulles
```

## Example

```python
import asyncio
import os

from aiohttp import ClientSession
from pyecobulles import EcobullesClient


async def main() -> None:
    async with ClientSession() as session:
        client = EcobullesClient(
            session,
            email=os.environ["ECOBULLES_EMAIL"],
            password=os.environ["ECOBULLES_PASSWORD"],
        )
        boxes = await client.list_devices()
        for box in boxes:
            eco_ref = box["eco_ref"]
            print(box["name"], await client.get_total_water_and_co2_usage(eco_ref))
            print(await client.get_device_info(eco_ref))
            print(await client.get_alerts(eco_ref))


asyncio.run(main())
```

The caller owns the `aiohttp.ClientSession`. `EcobullesClient` maintains the portal cookies in memory and automatically signs in again after an HTTP 401 or 403. This also works with a session whose cookie jar does not persist cookies, such as a shared Home Assistant web session.

## Available methods

- `authenticate(email, password)` returns `(success, user_id, first_eco_ref, first_box_name)` for callers of the previous library version. For accounts with several boxes, use `list_devices()`.
- `list_devices()` returns the boxes associated with the signed-in account. `account_id` exposes the authenticated portal account identifier after login.
- `get_total_water_and_co2_usage(eco_ref)` returns the current box water counter (`total_eau`, in L), the portal's raw gas counter (`total_gas`) and the last graph timestamp. The gas counter is an injection-time counter, **not kilograms of CO₂**.
- `get_device_info(eco_ref)` returns device metadata in the earlier `data.boite` shape, including the latest `bottle_empty` reading when available.
- `get_alerts(eco_ref)` returns the portal's alert records, including their `currently` flag.
- `get_configuration(eco_ref)` and `get_readings(eco_ref)` expose the portal's read-only raw configuration and sensor payloads.
- `get_login_payload(email, password)` returns an earlier mobile-API-compatible payload, including alerts, for existing integrations.

The package only reads data. It does not send activation, suspension, actuator or configuration commands. Portal fields and endpoints are reverse engineered and may change without notice.

The current `total_eau` counter can reset when the CO₂ bottle changes. Consumers that need lifetime accounting should track resets separately. The portal may report `total_gas = 0` (or omit it); the library returns the actual value (or `None`) without estimating consumption. Each box is queried separately using its own `eco_ref`.

## Compatibility

Python 3.12 or newer and `aiohttp` 3.9 or newer are supported. The package is typed and accepts an injected clock (`now_fn`) for applications and tests.

This project is not affiliated with Ecobulles. If the portal API changes, please report the affected endpoint and a redacted response shape in [GitHub Issues](https://github.com/jul-fls/pyecobulles/issues). Do not post passwords, cookies or full device dumps.
