import datetime import calendar from typing import List from fastapi import FastAPI from fastapi.responses import RedirectResponse from calculator.miner import get_energy_prices, get_eur_czk_ratio from calculator.schema import CheapestHours, DayPrice, Price from .consts import VAT def days_in_month(year: int, month: int) -> int: return calendar.monthrange(year, month)[1] app = FastAPI(title="Spot market home calculator", version="0.1", description="Calculate your energy costs based on spot market prices") @app.get("/", description="Redirect to /docs") def docs(): return RedirectResponse(url="/docs") docs = """ Return spot prices for the whole day with all fees included.

Options:
date - date in format YYYY-MM-DD, default is today
hour - hour of the day, default is current hour, works only when date is today
monthly_fees - monthly fees, default is 509.24 (D57d, BezDodavatele)
daily_fees - daily fees, default is 4.18 (BezDodavatele)
kwh_fees_low - additional fees per kWh in low tariff, usually distribution + other fees, default is 1.62421 (D57d, BezDodavatele)
kwh_fees_high - additional fees per kWh in high tariff, usually distribution + other fees, default is 1.83474 (D57d, BezDodavatele)
sell_fees - selling energy fees, default is 0.45 (BezDodavatele)
num_cheapest_hours - number of cheapest hours to return, default is 8, use this to plan your consumption
low_tariff_hours - list of low tariff hours, default is 0,1,2,3,4,5,6,7,9,10,11,13,14,16,17,18,20,21,22,23 (D57d, ČEZ)

Output:
spot - current spot prices on our market
total - total price for the day including all fees and VAT
sell - current spot prices minus sell_fees

The final price on the invoice is calculated as:
monthly_fees + kWh consumption in low tariff * kwh_fees_low + kWh consumption in high tariff * kwh_fees_high

Except spot and sell prices all prices include VAT.


Integration into Home Assistant can be done in configuration.yaml file:

``` sensor: - platform: rest resource: "https://pricepower2.rostiapp.cz/price/day" name: "energy_price" value_template: "{{ value_json.total.now|round(2) }}" unit_of_measurement: "CZK/kWh" - platform: rest resource: "https://pricepower2.rostiapp.cz/price/day" name: "energy_market_price" value_template: "{{ value_json.spot.now|round(2) }}" unit_of_measurement: "CZK/kWh" - platform: rest resource: "https://pricepower2.rostiapp.cz/price/day" name: "energy_market_price_sell" value_template: "{{ value_json.sell.now|round(2) }}" unit_of_measurement: "CZK/kWh" - platform: rest resource: "https://pricepower2.rostiapp.cz/price/day" name: "energy_cheap_hour" value_template: "{{ value_json.cheapest_hours.is_cheapest }}" ``` """ @app.get("/price/day", description=docs) @app.get("/price/day/{date}", description=docs) def read_item( date: datetime.date=datetime.date.today(), hour:int=datetime.datetime.now().hour, monthly_fees: float = 509.24, daily_fees: float=4.18, kwh_fees_low: float=1.62421, kwh_fees_high: float=1.83474, sell_fees: float=0.45, low_tariff_hours:str="0,1,2,3,4,5,6,7,9,10,11,13,14,16,17,18,20,21,22,23", no_cache:bool = False, num_cheapest_hours:int = 8, ) -> DayPrice: is_today = datetime.date.today() == date low_tariff_hours_parsed = [int(x.strip()) for x in low_tariff_hours.split(",")] monthly_fees = (monthly_fees + daily_fees * days_in_month(date.year, date.month)) monthly_fees_hour = monthly_fees / days_in_month(date.year, date.month) / 24 currency_ratio = get_eur_czk_ratio(date, no_cache=no_cache) spot_hours = {} spot_hours_for_sell = {} spot_hours_total = {} spot_data = get_energy_prices(date, no_cache=no_cache) for hour, value in spot_data.items(): kwh_fees = kwh_fees_low if int(hour) in low_tariff_hours_parsed else kwh_fees_high spot_hours[hour] = value / currency_ratio spot_hours_total[hour] = (value / currency_ratio + kwh_fees) * VAT spot_hours_for_sell[hour] = value / currency_ratio - sell_fees spot = Price(hours=spot_hours, now=spot_hours[str(hour)] if is_today else None) spot_hours_total_sorted = {k: v for k, v in sorted(spot_hours_total.items(), key=lambda item: item[1])} spot_total = Price(hours=spot_hours_total_sorted, now=spot_hours_total[str(hour)] if is_today else None) spot_for_sell = Price(hours=spot_hours_for_sell, now=spot_hours_for_sell[str(hour)] if is_today else None) cheapest_hours = [int(k) for k, v in list(spot_hours_total_sorted.items())[0:num_cheapest_hours]] data = DayPrice( monthly_fees=monthly_fees * VAT, monthly_fees_hour=monthly_fees_hour * VAT, kwh_fees_low=kwh_fees_low * VAT, kwh_fees_high=kwh_fees_high * VAT, sell_fees=sell_fees, low_tariff_hours=low_tariff_hours_parsed, vat=VAT, spot=spot, total=spot_total, sell=spot_for_sell, cheapest_hours=CheapestHours(hours=cheapest_hours, is_cheapest=hour in cheapest_hours if is_today else None) ) return data