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.0.tar.gz (15.6 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.0-py3-none-any.whl (18.8 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: pypentairthermalwifi-0.1.0.tar.gz
  • Upload date:
  • Size: 15.6 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.0.tar.gz
Algorithm Hash digest
SHA256 1d57de42821da3b9c5b61fa92da4d5bf4486e403aac081765422ba9a71767e36
MD5 2d2ff97db6d4cd454d49f962062c87ad
BLAKE2b-256 37c358a2d2858a7b31ab274ae2c723871ab01891a6d6626c9322abeaf671dd32

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for pypentairthermalwifi-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 1a733dc951b5e3592b2fdfbdc31cfba469285a86e66a1c6a6c20ebfd5d6957a2
MD5 75d68d83f0a0a1db744cf61c66aa24ed
BLAKE2b-256 3c29da81276de31ba9b22c91bd9f049d56b532d97572a14290b96fbca547046c

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