hyponcloud 0.3.0
Python library for Hypontech Cloud API
License: MIT
Requires Python: >=3.11
Keywords: hypontech, solar, inverter, api, async

# Hypontech Cloud API Python Library

[![CI](https://github.com/jcisio/hyponcloud/actions/workflows/ci.yml/badge.svg)](https://github.com/jcisio/hyponcloud/actions/workflows/ci.yml)
[![codecov](https://codecov.io/gh/jcisio/hyponcloud/graph/badge.svg)](https://codecov.io/gh/jcisio/hyponcloud)
[![PyPI version](https://badge.fury.io/py/hyponcloud.svg)](https://badge.fury.io/py/hyponcloud)
[![Python versions](https://img.shields.io/pypi/pyversions/hyponcloud.svg)](https://pypi.org/project/hyponcloud/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

A Python library for interacting with the Hypontech Cloud API for solar inverter monitoring.

## Features

- Async/await support using aiohttp
- Get plant overview data (power, energy production, device status)
- Get plant list
- Get inverter list for each plant
- Get administrator information
- Automatic token management and refresh
- Built-in retry logic for rate limiting
- Type hints for better IDE support
- Comprehensive error handling

## Installation

```bash
pip install hyponcloud
```

## Quick Start

### Basic Usage

```python
import asyncio
from hyponcloud import HyponCloud

async def main():
    # Create client with your credentials
    async with HyponCloud("your_username", "your_password") as client:
        # Connect and authenticate
        await client.connect()

        # Get overview data
        overview = await client.get_overview()
        print(f"Current power: {overview.power}W")
        print(f"Today's energy: {overview.e_today}kWh")
        print(f"Total energy: {overview.e_total}kWh")

        # Get plant list
        plants = await client.get_list()
        print(f"Number of plants: {len(plants)}")

        # Get inverters for a specific plant
        if plants:
            inverters = await client.get_inverters(plants[0].plant_id)
            print(f"Number of inverters: {len(inverters)}")
            for inverter in inverters:
                print(f"  {inverter.model}: {inverter.power}W")

        # Get administrator information
        admin = await client.get_admin_info()
        print(f"Admin user: {admin.username}")
        print(f"Email: {admin.email}")

asyncio.run(main())
```

### Using with Custom aiohttp Session

```python
import aiohttp
from hyponcloud import HyponCloud

async def main():
    async with aiohttp.ClientSession() as session:
        client = HyponCloud("your_username", "your_password", session=session)

        await client.connect()
        overview = await client.get_overview()
        print(f"Power: {overview.power}W")

asyncio.run(main())
```

### Error Handling

```python
from hyponcloud import (
    HyponCloud,
    RequestError,
    AuthenticationError,
    RateLimitError,
)

async def main():
    try:
        async with HyponCloud("username", "password") as client:
            await client.connect()
            overview = await client.get_overview()
            print(f"Power: {overview.power}W")

    except AuthenticationError as e:
        print(f"Authentication failed: {e}")
    except RateLimitError as e:
        print(f"Rate limit exceeded: {e}")
    except RequestError as e:
        print(f"Connection error: {e}")

asyncio.run(main())
```

## API Reference

### HyponCloud

Main client class for interacting with the Hypontech Cloud API.

#### Methods

##### `__init__(username: str, password: str, session: aiohttp.ClientSession | None = None, timeout: int = 10)`

Initialize the client.

- `username`: Your Hypontech Cloud username
- `password`: Your Hypontech Cloud password
- `session`: Optional aiohttp ClientSession. If not provided, one will be created automatically.
- `timeout`: Request timeout in seconds (default: 10)

##### `async connect() -> None`

Authenticate with the API and retrieve access token.

**Raises:**
- `AuthenticationError`: Invalid credentials (HTTP 401)
- `RequestError`: Request failed (network error or server error HTTP 500+)
- `RateLimitError`: Too many requests (HTTP 429)

##### `async get_overview(retries: int = 3) -> OverviewData`

Get plant overview data including power generation and device status.

**Parameters:**
- `retries`: Number of retry attempts on failure (default: 3)

**Returns:** `OverviewData` object

**Raises:**
- `AuthenticationError`: Authentication required
- `RequestError`: Request failed
- `RateLimitError`: Too many requests

##### `async get_list(retries: int = 3) -> list[PlantData]`

Get list of plants associated with the account.

**Parameters:**
- `retries`: Number of retry attempts on failure (default: 3)

**Returns:** List of `PlantData` objects

**Raises:**
- `AuthenticationError`: Authentication required
- `RequestError`: Request failed
- `RateLimitError`: Too many requests

##### `async get_inverters(plant_id: str, retries: int = 3) -> list[InverterData]`

Get all inverters for a specific plant. This method automatically fetches all pages of inverters.

**Parameters:**
- `plant_id`: The plant ID to get inverters for
- `retries`: Number of retry attempts on failure (default: 3)

**Returns:** List of `InverterData` objects

**Raises:**
- `AuthenticationError`: Authentication required
- `RequestError`: Request failed
- `RateLimitError`: Too many requests

##### `async get_admin_info(retries: int = 3) -> AdminInfo`

Get administrator account information.

**Parameters:**
- `retries`: Number of retry attempts on failure (default: 3)

**Returns:** `AdminInfo` object

**Raises:**
- `AuthenticationError`: Authentication required
- `RequestError`: Request failed
- `RateLimitError`: Too many requests

##### `async close() -> None`

Close the aiohttp session (only if created by the library).

### OverviewData

Data class containing plant overview information.

#### Attributes

- `capacity` (float): Plant capacity
- `capacity_company` (str): Capacity unit (e.g., "KW")
- `power` (int): Current power generation in watts
- `company` (str): Power unit (e.g., "W")
- `percent` (int): Percentage value
- `e_today` (float): Today's energy production in kWh
- `e_total` (float): Total lifetime energy production in kWh
- `fault_dev_num` (int): Number of faulty devices
- `normal_dev_num` (int): Number of normal devices
- `offline_dev_num` (int): Number of offline devices
- `wait_dev_num` (int): Number of devices waiting
- `total_co2` (int): Total CO2 savings
- `total_tree` (float): Equivalent trees planted

### PlantData

Data class containing individual plant information.

#### Attributes

- `city` (str): Plant location city
- `country` (str): Plant location country
- `e_today` (float): Today's energy production
- `e_total` (float): Total energy production
- `eid` (int): Equipment ID
- `kwhimp` (int): kWh import
- `micro` (int): Micro inverter count
- `plant_id` (str): Unique plant identifier
- `plant_name` (str): Plant name
- `plant_type` (str): Plant type
- `power` (int): Current power
- `status` (str): Plant status

### InverterData

Data class containing inverter information.

#### Attributes

- `plant_name` (str): Plant name
- `sn` (str): Serial number
- `gateway_sn` (str): Gateway serial number
- `status` (str): Inverter status
- `model` (str): Inverter model
- `software_version` (str): Software version
- `lcd_version` (str): LCD version
- `afci_version` (str): AFCI version
- `time` (str): Last update time
- `spn` (str): SPN identifier
- `power` (int): Current power output in watts
- `eid` (str): Equipment ID
- `device_type` (str): Device type
- `fault` (int): Fault status
- `plant_id` (str): Plant ID
- `modbus` (int): Modbus status
- `e_total` (float): Total energy production in kWh
- `e_today` (float): Today's energy production in kWh
- `property` (int): Property value
- `nick_name` (str): Nickname
- `com` (int): Communication status
- `system_connect_mode` (int): System connection mode
- `third_active_power` (int): Third party active power
- `third_meter_energy` (int): Third party meter energy
- `today_generation_third` (int): Today's generation from third party

### AdminInfo

Data class containing administrator account information.

#### Attributes

- `parent_name` (str): Parent account name
- `role` (list[str]): User roles
- `parent_id` (str): Parent account ID
- `has_lower_level` (bool): Whether account has lower level access
- `email` (str): User email address
- `username` (str): Username
- `first_name` (str): First name
- `last_name` (str): Last name
- `country` (str): Country
- `city` (str): City
- `language` (str): Language preference
- `currency` (str): Currency preference
- `timezone` (str): Timezone
- `last_login_time` (str): Last login timestamp
- `last_login_ip` (str): Last login IP address
- `id` (str): User ID
- And many other user profile fields

### Exceptions

- `HyponCloudError`: Base exception for all library errors
- `AuthenticationError`: Authentication failed (invalid credentials)
- `RequestError`: API request failed
- `RateLimitError`: API rate limit exceeded

## Development

### Setup Development Environment

```bash
# Clone the repository
git clone https://github.com/jcisio/hyponcloud.git
cd hyponcloud

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

# Set up pre-commit hooks (optional but recommended)
pre-commit install
```

### Running Tests

```bash
pytest
```

### Code Formatting

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

### Type Checking

```bash
mypy hyponcloud
```

### Version Management

This project uses `setuptools-scm` for automatic version management:

- Versions are automatically determined from git tags
- Use semantic versioning (e.g., `v0.1.2`)
- Create a git tag and push to trigger automated publishing via GitHub Actions

```bash
git tag v0.1.2
git push origin v0.1.2
```

## Requirements

- Python 3.11+
- aiohttp 3.8.0+
- mashumaro 3.11+

### Build Requirements

- setuptools-scm 8.0+ (automatically installed during build for version management)

## License

This project is licensed under the MIT License - see the LICENSE file for details.

## Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

## Disclaimer

This library is not officially associated with or endorsed by Hypontech. Use at your own risk.

## Support

For issues, questions, or contributions, please visit the [GitHub repository](https://github.com/jcisio/hyponcloud).