power-compare/app/config.py
dlawler489 1dbfe3007b
All checks were successful
Build and Push Docker Image / build-and-push (push) Successful in 24s
Share one iSolarCloud OAuth token across both household instances
Sungrow's OAuth server keeps only one active token session per (app,
account), not per plant -- with Kallangur and McDowall each managing their
own independent token against the same account, whichever one refreshed
last was silently invalidating the other's refresh token. Both instances
now share one token file (a common bind-mounted volume) instead of each
holding their own.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-13 08:04:30 +10:00

67 lines
3 KiB
Python

from pathlib import Path
from pydantic_settings import BaseSettings, SettingsConfigDict
class Settings(BaseSettings):
model_config = SettingsConfigDict(env_file=".env", env_file_encoding="utf-8", extra="ignore")
# Storage
db_path: str = "power_compare.db"
# iSolarCloud. "v1" = plain username/password login app; "oauth2" = a
# separate app type using the browser authorization-code flow. See
# SETUP.md -- these are two distinct developer-portal app registrations
# with different credentials, not two ways of using the same one.
isolarcloud_auth_mode: str = "v1" # "v1" | "oauth2"
isolarcloud_app_key: str = "" # "Appkey" from the developer portal
isolarcloud_app_secret: str = "" # "Secret key" / x-access-key from the developer portal
isolarcloud_region: str = "australia" # australia | europe | china | international
isolarcloud_plant_id: str = ""
# -- v1 auth mode only --
isolarcloud_username: str = "" # your regular iSolarCloud account (email/username)
isolarcloud_password: str = ""
# PEM-formatted RSA public key from the developer portal (Settings ->
# Open API), if your application was issued one. Some V1-login apps
# require the password to be RSA-encrypted before it's sent; when this
# is blank, the password is sent as plain text over HTTPS instead.
isolarcloud_rsa_public_key: str = ""
# -- oauth2 auth mode only --
isolarcloud_oauth_app_id: str = "" # "applicationId" from the developer portal
isolarcloud_oauth_redirect_uri: str = "https://localhost:8000/isolarcloud/callback"
# If this app is deployed as more than one independent instance against
# the SAME iSolarCloud account (e.g. two households' plants under one
# family member's login), Sungrow's OAuth server only keeps one active
# token session per (app, account) alive -- each instance refreshing its
# own token independently silently invalidates every other instance's
# refresh token. Pointing every instance at the same file here (a path
# under a volume shared/bind-mounted across all of them) makes them
# share one token session instead of fighting over it. Leave blank for a
# single-instance deployment; tokens then stay in this instance's own
# DB as before.
isolarcloud_shared_token_path: str = ""
# Set to true until real credentials are configured; the scheduler then
# polls app.isolarcloud.mock_client instead of the real API.
use_mock_isolarcloud: bool = True
# Household / AER plan scoping -- must match a substring of the
# distributor name AER plan data uses (e.g. "Energex" or "Ergon").
distributor: str = "Energex"
postcode: str = ""
# Scheduler cadence
isolarcloud_poll_interval_minutes: int = 10
aer_refresh_interval_hours: int = 24
aer_base_url: str = "https://cdr.energymadeeasy.gov.au"
@property
def db_url(self) -> str:
return f"sqlite:///{Path(self.db_path).resolve()}"
settings = Settings()