Unofficial Python client for Caldera Spa API
Project description
pycaldera
Python client library for controlling Caldera spas via their cloud API.
Installation
pip install pycaldera
Usage
Asynchronous API
import asyncio
from pycaldera import AsyncCalderaClient, PUMP_OFF, PUMP_LOW, PUMP_HIGH
async def main():
async with AsyncCalderaClient("email@example.com", "password") as spa:
# Get current spa status
status = await spa.get_spa_status()
print(f"Current temperature: {status.water_temperature}°F")
# Get detailed live settings
settings = await spa.get_live_settings()
print(f"Target temperature: {settings.ctrl_head_set_temperature}°F")
# Control the spa
await spa.set_temperature(102) # Set temperature to 102°F
await spa.set_pump(1, PUMP_HIGH) # Set pump 1 to high speed
await spa.set_lights(True) # Turn on the lights
asyncio.run(main())
Synchronous API
For simpler use cases, a synchronous wrapper is also available:
from pycaldera import CalderaClient, PUMP_OFF, PUMP_LOW, PUMP_HIGH
with CalderaClient("email@example.com", "password") as spa:
# Get current spa status
status = spa.get_spa_status()
print(f"Current temperature: {status.water_temperature}°F")
# Get detailed live settings
settings = spa.get_live_settings()
print(f"Target temperature: {settings.ctrl_head_set_temperature}°F")
# Control the spa
spa.set_temperature(102) # Set temperature to 102°F
spa.set_pump(1, PUMP_HIGH) # Set pump 1 to high speed
spa.set_lights(True) # Turn on the lights
Both clients provide identical functionality, with the synchronous client simply wrapping the async one for convenience.
API Reference
AsyncCalderaClient
The main async client class for interacting with the spa. All operations must be performed within an async context manager:
async with AsyncCalderaClient(
email="email@example.com",
password="password",
timeout=10.0, # Optional: request timeout in seconds
debug=False, # Optional: enable debug logging
) as spa:
# All spa operations must be inside this block
await spa.get_spa_status()
await spa.set_temperature(102)
# etc...
CalderaClient
A synchronous wrapper around AsyncCalderaClient that provides the same functionality without requiring async/await:
with CalderaClient(
email="email@example.com",
password="password",
timeout=10.0, # Optional: request timeout in seconds
debug=False, # Optional: enable debug logging
) as spa:
# All spa operations can be called synchronously
spa.get_spa_status()
spa.set_temperature(102)
# etc...
Error Handling
All operations can raise these base exceptions:
AuthenticationError: When authentication fails or token expiresConnectionError: When network connection fails or API is unreachableSpaControlError: When the API returns an error response
Temperature Control
async with spa as client:
# Set temperature (80-104°F or 26.5-40°C)
try:
# Basic temperature setting
await client.set_temperature(102) # Fahrenheit
await client.set_temperature(39, "C") # Celsius
# Wait for spa to acknowledge the temperature change
await client.set_temperature(102, wait_for_ack=True)
# Control polling behavior when waiting for acknowledgment
await client.set_temperature(
102,
wait_for_ack=True,
polling_interval=5.0, # Check every 5 seconds
polling_timeout=120.0, # Time out after 2 minutes
)
# Manually wait for temperature acknowledgment
settings = await client.wait_for_temperature_ack(
expected_temp=102, # Expected temperature in Fahrenheit
interval=5.0, # Check every 5 seconds
timeout=120.0, # Time out after 2 minutes
)
except InvalidParameterError:
# Raised when temperature is outside valid range
# (80-104°F or 26.5-40°C)
pass
except SpaControlError:
# Raised when polling times out waiting for acknowledgment
pass
Pump Control
async with spa as client:
try:
await client.set_pump(1, PUMP_HIGH) # Set pump 1 to high speed
await client.set_pump(2, PUMP_LOW) # Set pump 2 to low speed
await client.set_pump(3, PUMP_OFF) # Turn off pump 3
except InvalidParameterError:
# Raised when:
# - pump_number is not 1, 2, or 3
# - speed is not PUMP_OFF (0), PUMP_LOW (1), or PUMP_HIGH (2)
pass
Light Control
async with spa as client:
try:
await client.set_lights(True) # Turn lights on
await client.set_lights(False) # Turn lights off
except SpaControlError:
# Raised when light control fails
pass
Status & Settings
async with spa as client:
try:
# Get basic spa status
status = await client.get_spa_status()
print(f"Online: {status.status == 'ONLINE'}")
# Get detailed live settings
settings = await client.get_live_settings()
print(f"Target temp: {settings.ctrl_head_set_temperature}°F")
except ConnectionError:
# Raised when spa is offline or unreachable
pass
except SpaControlError:
# Raised when API returns invalid data
pass
## Development
1. Clone the repository
2. Create a virtual environment:
```bash
python -m venv venv
source venv/bin/activate # or `venv\Scripts\activate` on Windows
- Install development dependencies:
pip install -r requirements-dev.txt
- Install pre-commit hooks:
pre-commit install
The pre-commit hooks will run automatically on git commit, checking:
- Code formatting (Black)
- Import sorting (isort)
- Type checking (mypy)
- Linting (pylint, ruff)
- YAML/TOML syntax
- Trailing whitespace and file endings
License
MIT License - see LICENSE file for details.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pycaldera-0.1.3.tar.gz.
File metadata
- Download URL: pycaldera-0.1.3.tar.gz
- Upload date:
- Size: 25.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1a64044b969bccc8c33c1fdd7b5513a8c2955c8aab621aa02d44f81a97f25826
|
|
| MD5 |
8f1ff9baab2b6dff7f0f8af4b9ff241d
|
|
| BLAKE2b-256 |
e835eb4d1f2bedd16afdf7b3e7cf20ba9ec186e744debe3f224719569d997158
|
Provenance
The following attestation bundles were made for pycaldera-0.1.3.tar.gz:
Publisher:
release.yaml on mwatson2/pycaldera
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pycaldera-0.1.3.tar.gz -
Subject digest:
1a64044b969bccc8c33c1fdd7b5513a8c2955c8aab621aa02d44f81a97f25826 - Sigstore transparency entry: 1361018667
- Sigstore integration time:
-
Permalink:
mwatson2/pycaldera@9bc95d63c06c5aa931ce761ebabb7a65d159fe69 -
Branch / Tag:
refs/tags/v0.1.3 - Owner: https://github.com/mwatson2
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yaml@9bc95d63c06c5aa931ce761ebabb7a65d159fe69 -
Trigger Event:
push
-
Statement type:
File details
Details for the file pycaldera-0.1.3-py3-none-any.whl.
File metadata
- Download URL: pycaldera-0.1.3-py3-none-any.whl
- Upload date:
- Size: 16.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7d01f5b22f4918f2690b36c93741f7bb9ccf4655a0d225b201ae0a64f3c4eb99
|
|
| MD5 |
a2946ca46c2df1e85aaf336e7631704d
|
|
| BLAKE2b-256 |
3836a5cf32d9b92abe0a370ef043e5b22b00d6d74dc8225ff74016341b244d3c
|
Provenance
The following attestation bundles were made for pycaldera-0.1.3-py3-none-any.whl:
Publisher:
release.yaml on mwatson2/pycaldera
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pycaldera-0.1.3-py3-none-any.whl -
Subject digest:
7d01f5b22f4918f2690b36c93741f7bb9ccf4655a0d225b201ae0a64f3c4eb99 - Sigstore transparency entry: 1361018711
- Sigstore integration time:
-
Permalink:
mwatson2/pycaldera@9bc95d63c06c5aa931ce761ebabb7a65d159fe69 -
Branch / Tag:
refs/tags/v0.1.3 - Owner: https://github.com/mwatson2
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yaml@9bc95d63c06c5aa931ce761ebabb7a65d159fe69 -
Trigger Event:
push
-
Statement type: