Skip to main content

Python library for interacting with Pentair Thermal WiFi API to control thermostats

Project description

pypentairthermalwifi

A Python library for interacting with the Pentair Thermal WiFi API to control thermostats.

Features

  • 🔄 Both sync and async client support
  • 🔐 Automatic session management
  • 🔁 Retry logic with exponential backoff
  • 📝 Full type hints
  • 🎯 Simple, intuitive API
  • ✅ Comprehensive test coverage

Vibe Coded with Claude Code...

Installation

pip install pypentairthermalwifi

Or using uv:

uv add pypentairthermalwifi

Quick Start

Synchronous Client

from pypentairthermalwifi import PentairThermalWifi

# Create client
client = PentairThermalWifi(
    email="your-email@example.com",
    password="your-password"
)

# Get all thermostats
response = client.get_thermostats()
for group in response.groups:
    for thermostat in group.thermostats:
        print(f"{thermostat.room}: {thermostat.temperature_celsius}°C")

# Get specific thermostat
thermostat = client.get_thermostat("1036918")
print(f"Current temperature: {thermostat.temperature_celsius}°C")

# Set manual temperature
client.set_manual_temperature("1036918", 21.5)

# Close the client when done
client.close()

Asynchronous Client

import asyncio
from pypentairthermalwifi import AsyncPentairThermalWifi

async def main():
    # Create async client
    async with AsyncPentairThermalWifi(
        email="your-email@example.com",
        password="your-password"
    ) as client:
        # Get all thermostats
        response = await client.get_thermostats()
        for group in response.groups:
            for thermostat in group.thermostats:
                print(f"{thermostat.room}: {thermostat.temperature_celsius}°C")

        # Get specific thermostat
        thermostat = await client.get_thermostat("1036918")
        print(f"Current temperature: {thermostat.temperature_celsius}°C")

        # Set manual temperature
        await client.set_manual_temperature("1036918", 21.5)

asyncio.run(main())

Logging

The library includes comprehensive logging at different levels to help you understand what's happening:

  • DEBUG: Detailed request/response information, parameter values
  • INFO: High-level operations (authentication, fetching thermostats, updates)
  • WARNING: Retries, session expiry, non-critical issues
  • ERROR: Authentication failures, request failures

Enable Logging

import logging

# Configure logging (do this before creating the client)
logging.basicConfig(
    level=logging.INFO,  # or DEBUG for more detail
    format="%(asctime)s - %(name)s - %(levelname)s - %(message)s"
)

from pypentairthermalwifi import PentairThermalWifi

client = PentairThermalWifi(email="user@example.com", password="pass")
# You'll now see log messages as operations occur

Demo Applications with Logging

The demo applications support logging via the LOG_LEVEL environment variable. When set to INFO or DEBUG, httpx logging is also enabled to show HTTP requests and responses:

# Run with INFO level logging (shows library operations + HTTP requests)
export LOG_LEVEL=INFO
uv run python demo.py

# Run with DEBUG level logging (maximum detail including connection events)
export LOG_LEVEL=DEBUG
uv run python demo.py

Example output with LOG_LEVEL=INFO:

16:30:45 - pypentairthermalwifi.sync_client - INFO - Authenticating as user@example.com
16:30:45 - httpx - DEBUG - HTTP Request: GET https://www.pentairthermalwifi.com/api/authenticate
16:30:46 - pypentairthermalwifi.sync_client - INFO - Authentication successful, session ID: rm3w7zLJ...

Demo Applications

Two interactive demo applications are included to test the library:

Synchronous Demo

# Run with environment variables
export PENTAIR_EMAIL="your-email@example.com"
export PENTAIR_PASSWORD="your-password"
uv run python demo.py

# Or enter credentials interactively
uv run python demo.py

Asynchronous Demo

# Run with environment variables
export PENTAIR_EMAIL="your-email@example.com"
export PENTAIR_PASSWORD="your-password"
uv run python demo_async.py

# Or enter credentials interactively
uv run python demo_async.py

Both demos provide an interactive menu to:

  • 📋 List all thermostats with status
  • 🔍 View detailed information for a specific thermostat
  • 🌡️ Set temperature with confirmation
  • ✨ See real-time heating status and online state

Usage

Temperature Conversion

The API uses temperatures in 1/100 degrees Celsius (e.g., 2100 = 21.0°C). Helper functions are provided:

from pypentairthermalwifi import temp_to_celsius, celsius_to_temp

# Convert from API format to Celsius
celsius = temp_to_celsius(2100)  # 21.0

# Convert from Celsius to API format
raw = celsius_to_temp(21.0)  # 2100

All thermostat models have convenient properties for temperature access:

thermostat = client.get_thermostat("1036918")

# Access temperatures in Celsius
print(thermostat.temperature_celsius)
print(thermostat.manual_temperature_celsius)
print(thermostat.comfort_temperature_celsius)
print(thermostat.min_temp_celsius)
print(thermostat.max_temp_celsius)

Advanced Usage

Custom Thermostat Update

# Get the current thermostat state
thermostat = client.get_thermostat("1036918")

# Modify settings
thermostat.regulation_mode = 5  # Auto mode
thermostat.selected_schedule = 2  # Use program 3

# Update the thermostat
response = client.update_thermostat("1036918", thermostat)
print(f"Update successful: {response.success}")

Error Handling

from pypentairthermalwifi import (
    PentairThermalWifi,
    AuthenticationError,
    ThermostatNotFoundError,
    SessionExpiredError,
    APIError
)

try:
    client = PentairThermalWifi(email="user@example.com", password="wrong")
    client.authenticate()
except AuthenticationError as e:
    print(f"Authentication failed: {e}")

try:
    thermostat = client.get_thermostat("invalid-serial")
except ThermostatNotFoundError as e:
    print(f"Thermostat not found: {e}")

try:
    response = client.get_thermostats()
except SessionExpiredError as e:
    print(f"Session expired: {e}")
    # Client will automatically re-authenticate on next request

except APIError as e:
    print(f"API error: {e}")

Using Context Managers

# Sync client
with PentairThermalWifi(email="user@example.com", password="pass") as client:
    thermostats = client.get_thermostats()
    # Client automatically closes when exiting the context

# Async client
async with AsyncPentairThermalWifi(email="user@example.com", password="pass") as client:
    thermostats = await client.get_thermostats()
    # Client automatically closes when exiting the context

API Reference

PentairThermalWifi / AsyncPentairThermalWifi

Both clients support the same methods (async versions return coroutines).

Constructor

client = PentairThermalWifi(
    email: str,
    password: str,
    max_retries: int = 3,
    timeout: float = 30.0
)

Methods

  • authenticate() -> AuthResponse: Manually authenticate and get session ID
  • get_thermostats() -> ThermostatsResponse: Get all thermostats grouped by groups
  • get_thermostat(serial_number: str) -> Thermostat: Get a specific thermostat by serial number
  • update_thermostat(serial_number: str, thermostat: Thermostat) -> UpdateThermostatResponse: Update thermostat settings
  • set_manual_temperature(serial_number: str, temperature_celsius: float) -> UpdateThermostatResponse: Set manual temperature for a thermostat
  • close(): Close the HTTP client (async: await client.close())

Models

  • Thermostat: Complete thermostat data with temperature properties
  • Group: Thermostat group containing multiple thermostats
  • ThermostatsResponse: Response containing all groups
  • Schedule: Thermostat program/schedule
  • AuthResponse: Authentication response

Exceptions

  • PentairThermalWifiError: Base exception for all library errors
  • AuthenticationError: Raised when authentication fails
  • SessionExpiredError: Raised when session expires (auto-recovery enabled)
  • ThermostatNotFoundError: Raised when thermostat is not found
  • APIError: Raised on API errors

Development Setup

This project uses uv for dependency management and packaging.

Installation

# Install dependencies
uv sync --all-extras

Running Tests

# Run tests with coverage
uv run pytest

# Run tests with verbose output
uv run pytest -v

# Run tests with coverage report
uv run pytest --cov-report=html

Code Quality

# Run linting
uv run ruff check .

# Run linting with auto-fix
uv run ruff check --fix .

# Format code
uv run ruff format .

# Type checking
uv run mypy src/

All Checks

Run all quality checks before committing:

uv run ruff check . && uv run ruff format --check . && uv run mypy src/ && uv run pytest

Building

# Build package
uv build

Project Structure

pypentairthermalwifi/
├── src/
│   └── pypentairthermalwifi/
│       ├── __init__.py
│       └── py.typed
├── tests/
│   ├── __init__.py
│   └── test_pypentairthermalwifi.py
├── pyproject.toml
└── README.md

License

Add your license here.

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

pypentairthermalwifi-0.1.2.tar.gz (16.3 kB view details)

Uploaded Source

Built Distribution

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

pypentairthermalwifi-0.1.2-py3-none-any.whl (19.6 kB view details)

Uploaded Python 3

File details

Details for the file pypentairthermalwifi-0.1.2.tar.gz.

File metadata

  • Download URL: pypentairthermalwifi-0.1.2.tar.gz
  • Upload date:
  • Size: 16.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.3

File hashes

Hashes for pypentairthermalwifi-0.1.2.tar.gz
Algorithm Hash digest
SHA256 3339a3712418a9fd80bbf07305c01db38de4c7f7b1ffd167e85f5abfa152a057
MD5 a64a337b5a75bf4b81c07892dd319573
BLAKE2b-256 b4f53d5395aa8198ca7b43ace416f4aa4de8e161694fd53b035cae0f965d69b9

See more details on using hashes here.

File details

Details for the file pypentairthermalwifi-0.1.2-py3-none-any.whl.

File metadata

File hashes

Hashes for pypentairthermalwifi-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 aedc9f0b76f019e9a5507f1e29715cbe83bb59b87e776b0f47320a08e248dc95
MD5 1a53cbb13daa7b2a2dd120d2fe31a534
BLAKE2b-256 3677d76931c474bf227c345730f9868a7e80add5acb82bcbf2df9203586e0255

See more details on using hashes here.

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