|
| 1 | +#!/usr/bin/env python3 |
| 2 | +from base64 import b64encode |
| 3 | +from datetime import datetime, timezone, timedelta |
| 4 | +from urllib.parse import quote |
| 5 | +from typing import Dict |
| 6 | +from modules.common import req |
| 7 | +from modules.common.abstract_device import DeviceDescriptor |
| 8 | +from modules.common.component_state import TariffState |
| 9 | +from modules.electricity_tariffs.ostrom.config import OstromTariffConfiguration |
| 10 | +from modules.electricity_tariffs.ostrom.config import OstromTariff |
| 11 | + |
| 12 | + |
| 13 | +def fetch_prices(config: OstromTariffConfiguration) -> Dict[int, float]: |
| 14 | + access_token = req.get_http_session().post( |
| 15 | + url="https://auth.production.ostrom-api.io/oauth2/token", |
| 16 | + data={"grant_type": "client_credentials"}, |
| 17 | + headers={ |
| 18 | + "accept": "application/json", |
| 19 | + "content-type": "application/x-www-form-urlencoded", |
| 20 | + "authorization": "Basic " + b64encode((config.client_id + ":" + config.client_secret).encode()).decode() |
| 21 | + } |
| 22 | + ).json()["access_token"] |
| 23 | + utcnow = datetime.now(timezone.utc) |
| 24 | + startDate = quote(utcnow.strftime("%Y-%m-%dT%H:00:00.000Z")) |
| 25 | + endDate = quote((utcnow + timedelta(days=1)).strftime("%Y-%m-%dT%H:00:00.000Z")) |
| 26 | + if config.zip: |
| 27 | + zip = f"&zip={config.zip}" |
| 28 | + else: |
| 29 | + zip = "" |
| 30 | + raw_prices = req.get_http_session().get( |
| 31 | + url="https://production.ostrom-api.io/spot-prices?" + |
| 32 | + f"startDate={startDate}&endDate={endDate}&resolution=HOUR{zip}", |
| 33 | + headers={ |
| 34 | + "accept": "application/json", |
| 35 | + "authorization": "Bearer " + access_token |
| 36 | + } |
| 37 | + ).json()["data"] |
| 38 | + prices: Dict[int, float] = {} |
| 39 | + for raw_price in raw_prices: |
| 40 | + # Note: with Python >= 3.11, we can use: timestamp = datetime.fromisoformat(raw_price["date"]).timestamp() |
| 41 | + timestamp = datetime.strptime(raw_price["date"], "%Y-%m-%dT%H:%M:%S.000Z")\ |
| 42 | + .replace(tzinfo=timezone.utc).timestamp() |
| 43 | + price = float(raw_price["grossKwhPrice"] + raw_price["grossKwhTaxAndLevies"]) / 100000 # ct/kWh --> EUR/Wh |
| 44 | + prices.update({str(int(timestamp)): price}) |
| 45 | + return prices |
| 46 | + |
| 47 | + |
| 48 | +def create_electricity_tariff(config: OstromTariff): |
| 49 | + def updater(): |
| 50 | + return TariffState(prices=fetch_prices(config.configuration)) |
| 51 | + return updater |
| 52 | + |
| 53 | + |
| 54 | +device_descriptor = DeviceDescriptor(configuration_factory=OstromTariff) |
0 commit comments