Skip to main content

Async Python client for the Aranet Cloud REST API

Project description

aranet-cloud

python license release pypi

Async Python client for the Aranet Cloud REST API.

Wraps the public Aranet Cloud OpenAPI 3.0 spec — 25 of its 27 read-only GET endpoints (all but the two attachment-metadata endpoints) — and returns typed dataclass models. Designed primarily as the backing library for the aranet-cloud-homeassistant HACS integration, but usable as a standalone Python client.

Status: Alpha (0.2.x). The OpenAPI mapping is stable; the public Python surface may still evolve as the HA integration drives requirements. Pin to a minor version in production.

Install

pip install aranet-cloud

Python 3.11+ required. Single runtime dependency: aiohttp.

Quick start

import asyncio
from aranet_cloud import AranetCloudClient

async def main() -> None:
    async with AranetCloudClient(api_key="...") as client:
        # List every sensor on your account
        sensors = await client.get_sensors()
        for s in sensors:
            print(f"  {s.serial}  {s.name:<30s}  type={s.type}")

        # Latest reading per (sensor × metric), with name resolution
        readings, links = await client.get_measurements_last()
        for r in readings:
            metric = links.name("metric", r.metric) or r.metric
            unit   = links.name("unit",   r.unit)   or r.unit
            print(f"  {r.sensor:>10s}  {metric:>22s}: {r.value} {unit}")

asyncio.run(main())

Output against a typical home/garden account:

  A0005  Bedroom               type=S4V1
  A0001  Kitchen                       type=S4V1
  ...

  4000005           Temperature: 72.5 °F
  4000005              Humidity: 30 %
  4000005                    CO₂: 757 ppm
  4000005   Atmospheric Pressure: 697.9 mmHg
  ...

Authentication

The Aranet Cloud API uses a single header — ApiKey: <your-key>. No OAuth, no token refresh. Generate a key from your Aranet Cloud dashboard under Account → API.

AranetCloudClient(api_key="vku...")

What's covered

25 of the 27 GET endpoints in the public OpenAPI spec (all but the two attachment-metadata endpoints — the file/thumbnail downloads are wrapped):

Domain Methods
Sensors get_sensors, get_sensor, get_sensor_types, get_sensor_type
Measurements get_measurements_last, iter_measurements_history (paginated)
Telemetry get_telemetry_last, iter_telemetry_history (paginated)
Bases get_bases, get_base
Alarms get_alarms_actual, get_alarms_history, get_alarm_rules, get_alarm_rule
Assets get_assets, get_asset
Tags get_tags, get_tag
Catalog get_metrics, get_metric, get_unit
Attachments download_sensor_attachment, download_asset_attachment

See docs/architecture.md for the full API reference, edge cases discovered during live probing, and design notes.

Pagination

History endpoints are paginated by the server. The library hides the mechanics via async iterators:

async for reading in client.iter_measurements_history(sensor="4000005", hours=24):
    print(reading.time, reading.value)

The iterator follows the next token transparently until the server returns no more data. Mind the time windows/measurements/history without a sensor filter caps at 7 days; with a sensor filter it caps at 6 months.

Exception hierarchy

AranetError                       ← base; catch this for a blanket handler
├── AranetConnectionError         ← network, timeout, TLS, DNS
├── AranetAuthError               ← 401 (key wrong/missing/revoked) - NOT transient
├── AranetValidationError         ← 400 (carries correlation_id from API)
├── AranetRateLimitError          ← 429 (with retry_after if present)
├── AranetServerError             ← 5xx after exhausted retries
└── AranetNotFoundError           ← 404 (rare; API often returns 200 {} instead)

Auth errors deserve special handling — the Aranet API returns 401 as plain text (not JSON), so AranetAuthError doesn't carry a correlation ID. Validation errors are JSON with error[].id correlation tokens, preserved on AranetValidationError.correlation_id for support escalations.

Design

  • Async-first (aiohttp). Use as an async context manager (auto session) or inject an existing ClientSession — the HA-friendly pattern.
  • Typed: every response shape modelled as a dataclass with from_dict that ignores unknown fields, forward-compatible with new server fields.
  • Pagination hidden: iter_*_history() async generators follow next tokens transparently.
  • Retry/backoff on 5xx, 429, and transient network failures. Exponential backoff 1s, 2s, 4s, … capped at 30 s; 3 retries by default (so 1s, 2s, 4s). A server Retry-After on 429 is honoured — also clamped to the 30 s cap, so a hostile/misconfigured value can't stall the caller.
  • Polite-spacing floor (250 ms) between successive requests. The Aranet API has no documented rate limit, but we don't hammer.
  • Never logs the API key. Debug logs cover request method, path, status, and body size; the key is in headers only.

Standalone usage outside Home Assistant

The library has no HA dependencies and is fine to use in standalone Python scripts, FastAPI services, data-ingestion pipelines, etc.:

async with AranetCloudClient(api_key="...") as client:
    # Pull 24 hours of CO₂ readings for a single sensor
    readings = [
        r async for r in client.iter_measurements_history(
            sensor="4000005", metric="3", hours=24,
        )
    ]
    print(f"got {len(readings)} CO₂ samples")

Development

git clone https://github.com/jasonjhofmann/aranet-cloud
cd aranet-cloud
python -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"

pytest               # 50 tests
ruff check .         # lint
mypy src             # type-check (strict)
uv build             # build wheel + sdist (what CI publishes)

License

Apache 2.0

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

aranet_cloud-0.2.2.tar.gz (58.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

aranet_cloud-0.2.2-py3-none-any.whl (28.5 kB view details)

Uploaded Python 3

File details

Details for the file aranet_cloud-0.2.2.tar.gz.

File metadata

  • Download URL: aranet_cloud-0.2.2.tar.gz
  • Upload date:
  • Size: 58.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for aranet_cloud-0.2.2.tar.gz
Algorithm Hash digest
SHA256 ec10bd8362af5f3d7777e3a64596fdbcd4e8a201efda205410757ee764db1848
MD5 b9b501bbfa0559dab6627d0bd13122ec
BLAKE2b-256 e718ca88c9ad1928856ee3e323640769cd0149eed6ea02525b2554ef4493783a

See more details on using hashes here.

Provenance

The following attestation bundles were made for aranet_cloud-0.2.2.tar.gz:

Publisher: publish.yml on jasonjhofmann/aranet-cloud

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file aranet_cloud-0.2.2-py3-none-any.whl.

File metadata

  • Download URL: aranet_cloud-0.2.2-py3-none-any.whl
  • Upload date:
  • Size: 28.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for aranet_cloud-0.2.2-py3-none-any.whl
Algorithm Hash digest
SHA256 a40ddb8ab0a2f6c990d2f883dcef0ec0dc01dd128612e0a773f366a73c328179
MD5 16651994ac47d0683c33ace3e777a186
BLAKE2b-256 c005bdf5e53896102418f91d4b82bb37122035269486bc89a39a798a85126877

See more details on using hashes here.

Provenance

The following attestation bundles were made for aranet_cloud-0.2.2-py3-none-any.whl:

Publisher: publish.yml on jasonjhofmann/aranet-cloud

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page