Water Meter
CPAU Water Meter Implementation
This module provides the CpauWaterMeter class for retrieving water meter usage data from paloalto.watersmart.com.
- class cpau.water_meter.CpauWaterMeter(username, password, headless=True, cache_dir=None)[source]
Bases:
objectRepresents a CPAU water meter and provides methods to retrieve usage data.
Supports four interval types: - billing: Billing period data (CPAU’s billing periods, roughly monthly) - monthly: Calendar month aggregation (sum of daily data by month) - daily: Daily aggregated usage - hourly: Hourly usage data
Note: Water meter data comes from paloalto.watersmart.com and requires browser automation (Playwright) for SAML/SSO authentication.
Example
>>> meter = CpauWaterMeter(username='user', password='pass') >>> usage = meter.get_usage('daily', start_date, end_date) >>> for record in usage: ... print(f"{record.date}: {record.import_kwh} gallons")
- __init__(username, password, headless=True, cache_dir=None)[source]
Initialize water meter with CPAU credentials.
- Parameters:
Note
First API call will trigger Playwright authentication (~15 seconds). Subsequent calls within 10 minutes reuse cached cookies (<1 second).
- get_usage(interval, start_date, end_date=None)[source]
Retrieve water usage data for the specified interval and date range.
- Parameters:
- Return type:
- Returns:
List of UsageRecord objects sorted by date
- Raises:
ValueError – If interval is invalid or date range is invalid
Notes
First call authenticates via Playwright (~15s)
Subsequent calls reuse session (~1s each)
import_kwh field contains gallons (not kWh)
export_kwh is always 0 for water
net_kwh equals import_kwh
- get_billing_usage(start_date, end_date=None)[source]
Convenience method for billing period data.
- Return type:
- get_monthly_usage(start_date, end_date=None)[source]
Convenience method for monthly aggregated data.
- Return type:
- get_hourly_usage(start_date, end_date=None)[source]
Convenience method for hourly data.
- Return type:
- get_availability_window(interval)[source]
Find the earliest and latest dates for which data is available.
- Parameters:
interval (
str) – One of ‘billing’, ‘monthly’, ‘daily’, ‘hourly’- Return type:
- Returns:
Tuple of (earliest_date, latest_date) or (None, None) if no data found
Notes
For water meter, all intervals make a single API call that returns all available data
For ‘monthly’: Returns the daily data availability window (since monthly aggregates daily)
Total execution time: typically 1-2 seconds (after initial authentication)
- Raises:
ValueError – If interval is invalid
CpauWaterMeter
- class cpau.water_meter.CpauWaterMeter(username, password, headless=True, cache_dir=None)[source]
Bases:
objectRepresents a CPAU water meter and provides methods to retrieve usage data.
Supports four interval types: - billing: Billing period data (CPAU’s billing periods, roughly monthly) - monthly: Calendar month aggregation (sum of daily data by month) - daily: Daily aggregated usage - hourly: Hourly usage data
Note: Water meter data comes from paloalto.watersmart.com and requires browser automation (Playwright) for SAML/SSO authentication.
Example
>>> meter = CpauWaterMeter(username='user', password='pass') >>> usage = meter.get_usage('daily', start_date, end_date) >>> for record in usage: ... print(f"{record.date}: {record.import_kwh} gallons")
Supported Intervals
billing- Billing period datamonthly- Monthly aggregated usagedaily- Daily usage datahourly- Hourly usage data
Authentication
Water meter authentication uses Playwright for SAML/SSO flow:
First authentication: ~15 seconds (Playwright/SAML)
Cached authentication: ~1 second (10-minute cache window)
Cache location:
~/.cpau/watersmart_cookies.json(default)
Example
from cpau import CpauWaterMeter from datetime import date # Create water meter (handles SAML/SSO authentication automatically) meter = CpauWaterMeter( username='user@example.com', password='password', cache_dir='~/.cpau' # Optional: cache cookies for fast re-auth ) # Get usage data records = meter.get_usage( interval='daily', start_date=date(2024, 12, 1), end_date=date(2024, 12, 31) ) # Water usage is in the import_kwh field (gallons, not kWh) for record in records: print(f"{record.date}: {record.import_kwh} gallons") # Check data availability earliest, latest = meter.get_availability_window('daily') print(f"Water data available from {earliest} to {latest}")
Note
Water meter data is stored in the
import_kwhfield of UsageRecord, but contains gallons instead of kWh. Theexport_kwhandnet_kwhfields are always 0.0 for water meters.- __init__(username, password, headless=True, cache_dir=None)[source]
Initialize water meter with CPAU credentials.
- Parameters:
Note
First API call will trigger Playwright authentication (~15 seconds). Subsequent calls within 10 minutes reuse cached cookies (<1 second).
- get_usage(interval, start_date, end_date=None)[source]
Retrieve water usage data for the specified interval and date range.
- Parameters:
- Return type:
- Returns:
List of UsageRecord objects sorted by date
- Raises:
ValueError – If interval is invalid or date range is invalid
Notes
First call authenticates via Playwright (~15s)
Subsequent calls reuse session (~1s each)
import_kwh field contains gallons (not kWh)
export_kwh is always 0 for water
net_kwh equals import_kwh
- get_billing_usage(start_date, end_date=None)[source]
Convenience method for billing period data.
- Return type:
- get_monthly_usage(start_date, end_date=None)[source]
Convenience method for monthly aggregated data.
- Return type:
- get_hourly_usage(start_date, end_date=None)[source]
Convenience method for hourly data.
- Return type:
- get_availability_window(interval)[source]
Find the earliest and latest dates for which data is available.
- Parameters:
interval (
str) – One of ‘billing’, ‘monthly’, ‘daily’, ‘hourly’- Return type:
- Returns:
Tuple of (earliest_date, latest_date) or (None, None) if no data found
Notes
For water meter, all intervals make a single API call that returns all available data
For ‘monthly’: Returns the daily data availability window (since monthly aggregates daily)
Total execution time: typically 1-2 seconds (after initial authentication)
- Raises:
ValueError – If interval is invalid
WatersmartSessionManager
Watersmart.com session manager with automatic cookie handling.
This module provides a session manager that: 1. Authenticates using Playwright (headless) 2. Extracts and manages session cookies 3. Provides requests.Session for API calls 4. Automatically re-authenticates on 401 errors
- class cpau.watersmart_session.WatersmartSessionManager(username, password, headless=True, cache_dir=None)[source]
Bases:
objectManages authenticated sessions for paloalto.watersmart.com.
Handles SAML/SSO authentication via Playwright and provides a requests.Session with valid cookies for API access.
Example
>>> manager = WatersmartSessionManager('username', 'password') >>> session = manager.get_session() >>> response = session.get('https://paloalto.watersmart.com/index.php/rest/v1/Chart/RealTimeChart') >>> data = response.json()
- authenticate()[source]
Authenticate with watersmart.com using Playwright.
Performs SAML/SSO login flow and extracts session cookies.
- is_authenticated()[source]
Check if we have valid authentication cookies.
- Returns:
True if authenticated, False otherwise
- Return type:
- class cpau.watersmart_session.WatersmartSessionManager(username, password, headless=True, cache_dir=None)[source]
Bases:
objectManages authenticated sessions for paloalto.watersmart.com.
Handles SAML/SSO authentication via Playwright and provides a requests.Session with valid cookies for API access.
Example
>>> manager = WatersmartSessionManager('username', 'password') >>> session = manager.get_session() >>> response = session.get('https://paloalto.watersmart.com/index.php/rest/v1/Chart/RealTimeChart') >>> data = response.json()
Low-level session manager for WaterSmart portal authentication. Most users should use
CpauWaterMeterinstead.- authenticate()[source]
Authenticate with watersmart.com using Playwright.
Performs SAML/SSO login flow and extracts session cookies.
- is_authenticated()[source]
Check if we have valid authentication cookies.
- Returns:
True if authenticated, False otherwise
- Return type: