Metadata-Version: 2.4
Name: apyhiveapi
Version: 0.1.5
Summary: An async Python library to interface with the Hive API
Author: Tom Wilkie
License-Expression: MIT
Project-URL: Homepage, https://github.com/tomwilkie/apyhiveapi
Project-URL: Source, https://github.com/tomwilkie/apyhiveapi
Project-URL: Issue Tracker, https://github.com/tomwilkie/apyhiveapi/issues
Keywords: hive,home,api,library,smart-home,home-automation,IoT,async,integration
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Home Automation
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.13
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: aiohttp
Requires-Dist: boto3>=1.34
Requires-Dist: botocore>=1.34
Provides-Extra: dev
Requires-Dist: pytest; extra == "dev"
Requires-Dist: pytest-asyncio; extra == "dev"
Requires-Dist: pytest-cov; extra == "dev"
Requires-Dist: pylint; extra == "dev"
Requires-Dist: ruff; extra == "dev"
Requires-Dist: mypy; extra == "dev"
Requires-Dist: bandit; extra == "dev"
Requires-Dist: pre-commit; extra == "dev"
Requires-Dist: build; extra == "dev"
Requires-Dist: bump-my-version; extra == "dev"
Dynamic: license-file

# apyhiveapi

![CI](https://github.com/tomwilkie/apyhiveapi/actions/workflows/ci.yml/badge.svg) ![PyPI](https://img.shields.io/pypi/v/apyhiveapi) ![License](https://img.shields.io/github/license/tomwilkie/apyhiveapi)

An async Python library for the [Hive](https://www.hivehome.com/) smart home platform. It exists to power [tomwilkie/ha-hive](https://github.com/tomwilkie/ha-hive), a fork of the Hive integration for [Home Assistant](https://www.home-assistant.io/), and exposes exactly what that integration needs: Hive heating (thermostats and TRVs) and hot water.

> This library is a hard fork of [Pyhass/Pyhive](https://github.com/Pyhass/Pyhive), cut down to what the ha-hive integration needs and restarted at version 0.0.1. It was called `pyhive-integration` until v0.1.5; that name on PyPI belongs to the upstream project, so this one is published as `apyhiveapi`, which is also the import name.

---

## Features

- Async only, built on `aiohttp`
- AWS Cognito SRP authentication with SMS two-factor authentication support
- Automatic token refresh at 90% of token lifetime, with a silent re-login when the refresh token is rejected
- Polling-based device state, rate limited to one poll per scan interval across all entities
- Full device discovery — returns a ready-to-use device list for the integration's entities
- File-based offline mode for development and testing without live credentials

## Supported Devices

| Device Type | Capabilities |
| --- | --- |
| **Heating** (thermostat, TRV) | Current / target temperature, mode (schedule / manual / off), boost on/off |
| **Hot Water** | Mode (schedule / on / off), boost on/off |

Lights, smart plugs, sensors and the hub are not supported: the ha-hive integration does not use them.

---

## Installation

From PyPI, or the current `main`:

```bash
pip install apyhiveapi
pip install "apyhiveapi @ git+https://github.com/tomwilkie/apyhiveapi"
```

Every release is also attached to its [GitHub Release](https://github.com/tomwilkie/apyhiveapi/releases) as a wheel and sdist.

Requires Python 3.13+.

---

## Quick Start

```python
import asyncio
import getpass

from aiohttp import ClientSession
from apyhiveapi import SMS_REQUIRED, Auth, Hive


async def main():
    username = input("Hive email: ")
    password = getpass.getpass("Hive password: ")

    auth = Auth(username=username, password=password)
    tokens = await auth.login()
    if tokens.get("ChallengeName") == SMS_REQUIRED:
        tokens = await auth.sms_2fa(input("SMS code: "), tokens)
        await auth.device_registration()

    async with ClientSession() as websession:
        hive = Hive(websession)
        devices = await hive.start_session(
            {
                "username": username,
                "password": password,
                "tokens": tokens,
                "device_data": auth.get_device_data(),
            }
        )
        for climate in devices["climate"]:
            await hive.heating.get_climate(climate)
            print(climate.ha_name, climate.status)


asyncio.run(main())
```

---

## Authentication

Authentication uses the AWS Cognito SRP flow. On the first login `login()` returns a
`ChallengeName` of `SMS_MFA` (the `SMS_REQUIRED` constant) when the account has SMS
two-factor authentication enabled; pass the code to `sms_2fa(code, tokens)`. Then call
`device_registration()` to register the machine as a trusted device and save the
credentials `get_device_data()` returns, so later sessions can log in without an SMS.

> **Note:** Only the Hive account owner is supported. Guest accounts cannot be used.

### Standalone login example

[`examples/example_login.py`](examples/example_login.py) is a complete runnable
script. The first run asks for your email, password and SMS code, registers the
machine as a trusted device and saves the device credentials to
`hive_device.json`. Later runs log in with that file and skip the SMS. Both runs
list every discovered device.

```bash
pip install apyhiveapi
python examples/example_login.py
```

---

## Controlling Devices

After `start_session`, device modules are available directly on the `Hive` instance.
Commands return nothing and raise a `HiveError` when the change could not be made;
readers never raise and report unknown values as `None`.

```python
# Heating
await hive.heating.set_target_temperature(device, 21.0)
await hive.heating.set_mode(device, "SCHEDULE")
await hive.heating.set_boost_on(device, 30, 22.0)
await hive.heating.set_boost_off(device)

# Hot water
await hive.hotwater.set_mode(device, "MANUAL")
await hive.hotwater.set_boost_on(device, 60)
await hive.hotwater.set_boost_off(device)

# Refresh state (rate limited to the configured scan interval)
await hive.update_data()
device = await hive.heating.get_climate(device)
print(device.status, device.device_data["online"])
```

---

## Errors

Every exception the library raises is a subclass of `HiveError`, grouped by what the
caller should do about it. aiohttp and botocore exceptions never escape the library.

| Exception | Meaning | What to do |
|---|---|---|
| `HiveConnectionError` | Hive or Cognito could not be reached, timed out, failed with a 5xx, sent an unreadable response, or returned no devices when the session started | Retry later |
| `HiveApiError` | Hive or Cognito refused the request or answered unexpectedly | Report it; retrying will not help |
| `HiveDeviceOffline` | A command was sent to a device that is offline or no longer on the account | Report it |
| `HiveReauthRequired` | The tokens, refresh token or saved device credentials were rejected, there are no tokens, or Hive wants an SMS code. The session then keeps raising it without contacting Hive until it is given new tokens | Log in again |
| `HiveInvalidUsername`, `HiveInvalidPassword`, `HiveInvalid2FACode` | Subclasses of `HiveReauthRequired` raised by the login flow | Show the user a form error |

Invalid arguments, such as a boost of zero minutes, raise `ValueError`. Polling through
`update_data` logs transient failures, keeps the last known state and retries after
30 seconds; only `HiveReauthRequired` propagates from it.

---

## Offline / File-Based Testing

Set `username="use@file.com"` to load device state from the bundled JSON fixture in `src/apyhiveapi/data/` instead of making live API calls. Useful for development without real Hive credentials.

```python
async with Hive(username="use@file.com", password="") as hive:
    await hive.start_session({})
```

---

## Development

```bash
# Install dev dependencies
pip install -e ".[dev]"

# Run linters
pre-commit run --all-files

# Run tests
pytest tests/
```

---

## Links

- [ha-hive](https://github.com/tomwilkie/ha-hive), the Home Assistant integration this library powers
- [Releases](https://github.com/tomwilkie/apyhiveapi/releases)
- [Source](https://github.com/tomwilkie/apyhiveapi)
- [Issue Tracker](https://github.com/tomwilkie/apyhiveapi/issues)

---

## License

MIT License — see [LICENSE](https://github.com/tomwilkie/apyhiveapi/blob/main/LICENSE) for details. The original work is copyright Pyhive; the changes in this fork are copyright Tom Wilkie.
