Rynkowe ceny energii elektrycznej

Cześć,

Od lipca 2024 energia sprzedawana do sieci ma być rozliczana na bazie cen godzinowych z rynku dnia następnego (Rynkowa cena energii elektrycznej (RCE) - PSE)

Zapewne część z was (podobnie jak ja) będzie chciało zoptymalizować sprzedawaną / wykorzystywaną energię więc podzielę się swoją templatką do codziennego pobierania stawek w danych godzinach.

Jako że to moja pierwsza templatka tworzona od zera to chętnie przyjmę propozycje usprawnień.

  1. Zaczynamy od edycji configuration.yaml. Dodajemy:
homeassistant:
  allowlist_external_dirs:
    - "/config/downloads"
    - "/config/downloads/energy_prices"

downloader:
  download_dir: downloads

# jeżeli nie mieliśmy do tej pory to także:
automation: !include automations.yaml
script: !include scripts.yaml
command_line: !include command_line.yaml
template: !include templates.yaml
  1. Dalej tworzymy skrypt (scripts.yaml), który zapisuje plik CSV pobrany z PSE do folderu config/download/energy_prices z nazwą taką jak w PSE. Wykorzystuje w tym celu standardową integrację Downloader.
download_pse_market_energy_prices:
  alias: Download PSE Market Energy Prices
  sequence:
    - data:
        filename: "{{ (now() + timedelta(days=1)).timestamp() | timestamp_custom('%Y%m%d') }}.csv"
        overwrite: true
        subdir: energy_prices
        url: "https://www.pse.pl/getcsv/-/export/csv/PL_CENY_RYN_EN/data/{{ (now() + timedelta(days=1)).timestamp() | timestamp_custom('%Y%m%d') }}"
      service: downloader.download_file
  icon: mdi:cash
  1. Następnie tworzymy automatyzację (automations.yaml) która raz dziennie odpala powyższy skrypt:
- id: 'xxxxxxxxxxxxxxxx'
  alias: Daily PSE Market Energy Price Download
  description: ''
  trigger:
  - platform: time
    at: 23:32:23
  action:
  - service: script.download_pse_market_energy_prices
  mode: single
  1. Na koniec command_line sensor (command_line.yaml) który przy każdej zmianie godziny pobiera nam ze ściągniętego pliku CSV linijkę odpowiadającą aktualnej godzinie:
sensor:
  name: pse_market_energy_price_current_hour
  unique_id: pse_market_energy_price_current_hour
  command: "cat -n /config/downloads/energy_prices/{{ now().timestamp() | timestamp_custom('%Y%m%d') }}.csv | sed '{{now().strftime('%H') | int + 2}}!d'"
  value_template: '{{value.split(";")[2] | regex_replace(find=",", replace=".") | float(0) }}'
  unit_of_measurement: "PLN/MWh"

Otrzymujemy encję, która podaje nam aktualną cenę w PLN/MWh:

Możemy wykorzystać ją jako warunek do automatyzacji lub po prostu podpiąć do dashboardu energii i zliczać całkowitą cenę oddanej energii (na screenshocie niska, bo dziś pochmurny dzień i magazyn dopiero się w pełni naładował):
image

Docelowo można pomyśleć o modyfikacji, żeby plik był pobierany dzień wcześniej wieczorem (dane są publikowane popołudniu), ale obecnie to jest poniżej minuty opóźnienia w odświeżaniu danych w dodatku w środku nocy.

3 Likes

Widziałem też coś takiego, można dodać repo w HACS

Rewelacyjny skrypt!

Osobiscie dokonalbym dwoch drobnych zmian - w sensorze zmienilbym

state: "{{ now().timestamp() | timestamp_custom('%Y%m%d') }}"

na

state: "{{ (now() + timedelta(days=1)).timestamp() | timestamp_custom('%Y%m%d') }}"

to daje jutrzejsza date i wtedy odpalalbym automatyzacje o jakiejs dziwnej godzinie, np 23:07 poniewaz odpalania skryptow o polnocy jest kiepskie, masa automatyki na serwerach odpala sie wtedy i masa ludzi wtedy bedzie powbierac te dane wiec serwer sie moze nie wyrobic, a tak trafiamy na spokojniejszy moment dla serwera i nie tracimy minuty rozliczen :slight_smile:

2 Likes

czyli po każdym przeładowaniu HA sensor będzie w stanie unavailable do czasu aż znów o pełnej godzinie pobierze wartość z pliku i będzie miał state? Zapewne wtedy panel energii się odezwie (jeśli zostanie użyty do określenia ceny) , że encja jest nienumeryczna.

Edit. Sprawdziłem z ciekawości bo temat mnie bardzo ciekawi i sam szukam jakiegoś rozwiązania. A więc rzeczywiście po restarcie HA encja jest unavailable , ponieważ nie ustawiono w konfiguracji sensora scan_interval więc powinien domyślnie wykonać update po 60s ale tego nie zrobił, dalej pozostawał unavailable, nawet zmiana godziny go nie wybudziła, dopiero wykonanie service: command_line.reload obudziło go to życia i dalej aktualizował się zgodnie. @kubaa czy u siebie też to obserwujesz ?

Zaktualizowałem dzisiaj HA do najnowszej wersji i sensor był rzeczywiście unavailable, log wyrzucił błąd:
ValueError: Template error: float got invalid input '' when rendering template '{{value.split(";")[2] | regex_replace(find=",", replace=".") | float }}' but no default was specified

Błąd niby sugerowałby niewłaściwą zawartość pliku, więc może wynika to z chwilowego braku dostępu do pliku podczas uruchomienia?
Po ponownym przeładowaniu tak jak u Ciebie wszystko zadziałało.

Tak to wygląda, ale zastanawia mnie dlaczego sensor nie wstaje “sam” po czasie scan_interval tylko trzeba wykonać command_line.reload ? Nie mam większego doświadczenia z tą integracją, mam raptem kilka czujników temperatury mojego della i one nie potrzebują “przeładowania” same wstają.


potem działa poprawnie.

Udało mi się to rozwiązać. Otóż okazuje się, że występuje jakaś dziwna kolejność ładowania sensorów i użyty sensor daty (i nazwy pliku) ładował się sporo później niż próbował załadować się sensor z ceną który z niego korzystał.

Tak więc pozbyłem się encji z datą i użyłem templatki w skrypcie oraz encji ceny. Szczególnie po wdrożeniu zmiany:

Dzięki, miałem to w planach ale skoro wkleiłeś kod to użyłem od razu u siebie.

Zaktualizowałem pierwszy post o obie zmiany.

3 Likes

hej, pogrzebalem jeszcze troche w kodzie i zrobilem dwie zmiany ktre sie moga przydac wszystkim

pierwsza:

  value_template: '{{value.split(";")[2] | regex_replace(find=",", replace=".") | float(0) }}'

dopisanie po float “(0)” daje nam zabezpiecznie jak np plik sie zle wczyta albo watosc sie nie bierze, zamiast bledu dostaniemy “0”

u siebie tak ustawilem i dzieki temu znalazlem blad w skrypcie

 command: "cat -n /config/downloads/energy_prices/{{ now().timestamp() | timestamp_custom('%Y%m%d') }}.csv | sed '{{now().strftime('%H') | int + 1}}!d'"

w tym poleceniu polecenie sed odczytuje numer linii dodajac do biezacej godziny 1, ale plik CSV ma naglowek, wiec musimy dodac nie 1 a 2 poniewaz plik tekstowy zaczyna sie od linii 1 a nie 0 ; )

inaczej mowiac majac godzine 00:00:00 tostaniemy “00” castowane na int’a + 1 czyli da nam linie numer jeden a w niej jest naglowek pliku csv z opisem kolumn, jak zrobimy + 2 wtedy odczyt sie zgadza.

zatem uprzejmie prosze abys @kubaa skorygowal pierwszy post zeby sobie ktos wersji z bledem nie wkleil w swoja konfiguracje.

poprawna wersja to:

 command: "cat -n /config/downloads/energy_prices/{{ now().timestamp() | timestamp_custom('%Y%m%d') }}.csv | sed '{{now().strftime('%H') | int + 2}}!d'"

swoja droga te pliki z odczytami sie zbieraja w tym katalogu downloads/energy_prices, jak ktos chce to moge podrzucic sposob automatycznego kasowania starych plikow

1 Like

hm … u mnie z “1” wydaje się być ok ? według Ciebie powinien mi wskazywac cenę z godziny 17 … ?


edit. właśnie kolejna zmiana i jest ok …

wg mnie kod jest poprawny z “1”.

Można jak proponujesz ale jak nie chcesz aby sie zbierały to chyba wystarczy zmienić atrybut … z true na …

overwrite: false

zaczne od konca, overwrite nadpisuje plik jesli ma te sama nazwe, tu kazdy ma inna wiec i tak sie beda zbierac, zeby overwrite mialo sens bys musial ustalic jedna nazwe pliku np ceny.csv i wtedy przy overwrite: yes bedzie go codziennie nadpisywac :wink:

A co do godzin to juz tlumacze, ponizej mamy przykladowy plik csv

obraz

jak mamy polecenie now().strftime('%H') | int to o polnocy danego dnia to nam zwroci wartosc “0” - jak dodamy 1 do wychodzi 1, czyli odczyta pierwsza linie z pliku, a pierwsza linia to naglowek “Data;Godzina;RCE”, zwroc uwage ze w pliku godziny sa od 1 do 24 a nie od 0 do 23, dlatego dla godziny 00:00 musisz odczytac wartosc z linii 2 dla godzyny “1”, a dla godziny 19 jak z Twojego przykladu powyzej musisz odczytac wartosc z linii 21 dla godziny “20”. wszystko jest przesuniete o jeden :wink:

Wiem ze to troche pokretne i mam nadzieje ze uda ci sie zrozumiec moje wytlumaczenie. Chwile nad tym siedzialem i analizowalem, zdecydowanie tak musi byc zeby sie zgadzalo, nie mniej sprawdz sobie sam dla pewnosci. mysle ze dojdziesz do tej samej konkluzji.

Dzięki, rzeczywiście trzeba dodać 2 a nie 1, bo indeksowanie jest od 1 a nie od 0.
Zaktualizowałem skrypty w pierwszym poście.

1 Like

Staram się jak mogę, ale chyba w tej kwestii to “beton”.

o 1:05 zwróci nam 1 co po dodaniu 2 da nam 3 wiersz a w nim …

Data;Godzina;RCE
20240412;1;347,08
20240412;2;342,44

cena dla energii pobieranej w godzinach 2-3 ? a my tymnczasem jesteśmy w godzinie 1+ :thinking:
… no chyba, że pobór od 00 - 01 to cena 1 a 01-02 to cena 2 …?

dokladnie o to chodzi

od 00 - 01 to cena 1 (z linii 2 w pliku)
od 01 - 02 to cena 2 (z linii 3 w pliku)

i tak dalej az do

od 23 - 00 to cena 24 (z linii 25 w pliku)

na tym polega ten “zakrecony” problem - tez chwile nad tym siedzialem
i dlatego tam musi byc to “+2” a nie “+1”

1 Like

Super sprawa, dzięki!

szybkie zmiany w HA, w najnowszej odsłonie downloader wylatuje z configuration.yaml do własnej integracji:
image