FastAPI app that pulls interval usage from Sungrow iSolarCloud (OAuth2), caches AER Consumer Data Right electricity plan data, and compares actual metered usage against every available plan to estimate real annual cost (TOU, tiered feed-in, and flat tariffs). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
55 lines
2.2 KiB
Python
55 lines
2.2 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"
|
|
|
|
# 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()
|