Metadata-Version: 2.4
Name: pyaprilaire-cloud
Version: 0.1.0
Summary: Async client for the Aprilaire cloud API (aprilaire.io) - E-series WiFi dehumidifiers and other cloud-connected Aprilaire devices
Author: Robert Borkowski
License: MIT
Project-URL: Homepage, https://github.com/rborkow/pyaprilaire-cloud
Project-URL: Issues, https://github.com/rborkow/pyaprilaire-cloud/issues
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Home Automation
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: aiohttp>=3
Requires-Dist: pycognito>=2024
Provides-Extra: dev
Requires-Dist: pytest; extra == "dev"
Requires-Dist: pytest-asyncio; extra == "dev"
Requires-Dist: pytest-cov; extra == "dev"
Requires-Dist: aioresponses; extra == "dev"
Requires-Dist: aiohttp<3.14; extra == "dev"
Requires-Dist: black; extra == "dev"
Requires-Dist: isort; extra == "dev"
Dynamic: license-file

# pyaprilaire-cloud

Async Python client for the Aprilaire cloud API (`*.aprilaire.io`) — the
REST API used by the AprilAire Healthy Air mobile app. Built for E-series
WiFi dehumidifiers (tested against a live E080W) and usable with any
cloud-connected Aprilaire device the API exposes.

For the local socket protocol used by 8800/6000-series thermostats, see
[pyaprilaire](https://github.com/chamberlain2007/pyaprilaire) — the two
protocols share nothing, which is why this lives in its own package.

## Features

- AWS Cognito SRP authentication via `pycognito`, with blocking calls run
  in an executor — safe inside asyncio event loops (e.g. Home Assistant)
- Typed errors: `CloudClientAuthError` (bad credentials) vs
  `CloudClientRequestError` (network/service), so callers can distinguish
  reauth from retry
- Automatic token refresh on 401, serialized behind a lock
- Injectable `aiohttp` session (only closes sessions it owns)
- Device hierarchy, dehumidifier status/settings reads, mode and humidity
  setpoint control

## Usage

```python
import asyncio
import logging

from pyaprilaire_cloud import AprilaireCloudClient


async def main() -> None:
    client = AprilaireCloudClient("you@example.com", "password", logging.getLogger())
    await client.authenticate()

    hierarchy = await client.get_hierarchy()
    device_id = hierarchy.device_ids[0]

    status = await client.get_dehumidifier_status(device_id)
    print(status.equipment_status, status.hum_sensors[0].reading)

    await client.set_dehumidifier_mode(device_id, "on")
    await client.set_dehumidification_setpoint(device_id, 50)

    await client.close()


asyncio.run(main())
```

## Notes

- The API is unofficial and reverse-engineered from the vendor app; it may
  change without notice.
- `PATCH` commands return 200 immediately; the device applies them in ~5
  seconds. Poll settings until the `asOf` timestamp updates to confirm.
- Setpoint range is 40–80%. Out-of-range writes are silently ignored by
  the device.

## Development

```bash
pip install -e ".[dev]"
pytest -v --cov=pyaprilaire_cloud tests/
black pyaprilaire_cloud tests && isort pyaprilaire_cloud tests
```
