Skip to content
/ opcom Public

OPCOM PZU România → senzori Home Assistant (PT15M/PT30M/PT60M), preț curent/următor, ferestre ieftin/scump (greedy), cross-day, diagnostics.

License

Notifications You must be signed in to change notification settings

cnecrea/opcom

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

55 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

OPCOM România — Integrare Home Assistant

HACS Custom GitHub Release

Integrare custom pentru Home Assistant care importă prețurile energiei electrice de pe OPCOM România — Piața pentru Ziua Următoare (PZU/DAM).

Oferă senzori în timp real pentru prețul curent, ferestre optime de cumpărare/vânzare, și semnale binare pentru automatizarea încărcării/descărcării bateriilor (sisteme de stocare energie, vehicule electrice, pompe de căldură etc.).


Ce face integrarea

  • Descarcă automat prețurile PZU de pe OPCOM.ro la interval configurabil (implicit: 15 minute)
  • Suportă 3 rezoluții: PT15M (96 intervale/zi), PT30M (48 intervale/zi), PT60M (24 intervale/zi)
  • Calculează ferestrele optime de preț ieftin/scump — non-suprapuse (algoritm greedy)
  • Senzori binari pentru automatizări: „Ar trebui să încarce acum?" / „Ar trebui să exporte acum?"
  • Cross-day: senzorii binari văd și prețurile de mâine (când sunt disponibile) — util seara
  • Filtrare viitor: senzorii de recomandare ignoră intervalele deja trecute
  • Intervale rămase: câte sloturi „bune" mai rămân azi (pentru planificarea bateriei)
  • Diagnostics complet: pagina de diagnostics expune toate datele raw pentru troubleshooting

Sursa datelor

Datele vin direct de pe OPCOM.ro, fișiere CSV publice:

https://www.opcom.ro/rapoarte-pzu-raportPIP-export-csv/{zi}/{luna}/{an}/{lang}?resolution={res}

OPCOM publică prețurile PZU (Piața pentru Ziua Următoare) în fiecare zi, de regulă între orele 13:00 și 15:00, pentru ziua următoare. Până la publicare, senzorii „mâine" afișează „Necunoscut" (Unknown) — comportament normal.


Referință de timp: CET, nu ora României

OPCOM operează pe CET (Central European Time = Europe/Berlin), nu pe ora României (EET = Europe/Bucharest). Asta e confirmat oficial de OPCOM:

„Toate aspectele legate de participarea pe PZU se raportează la ore CET."

Ce înseamnă concret:

  • Intervalul 1 din CSV = 00:00–00:15 CET = 01:00–01:15 ora României
  • Ultimul interval al zilei se termină la 00:00 CET = 01:00 ora României (ziua următoare)
  • Diferența e mereu 1 oră (iarna CET→EET = +1h, vara CEST→EEST = +1h — se schimbă simultan)

Integrarea gestionează asta automat pe două niveluri:

  • Calculele interne (intervalul curent, ziua de livrare, ferestrele optime) sunt făcute în CET — asigură sincronizarea exactă cu datele OPCOM
  • Orele afișate în atributele senzorilor (ex: ora: "22:45 → 23:45") sunt convertite automat în timezone-ul configurat în Home Assistant — nu trebuie să faci nicio conversie manuală

Nu trebuie să schimbi nimic în setările HA.


Instalare

HACS (recomandat)

  1. Deschide HACS în Home Assistant
  2. Click pe cele 3 puncte (⋮) din colțul dreapta sus → Custom repositories
  3. Adaugă URL-ul: https://github.com/cnecrea/opcom
  4. Categorie: Integration
  5. Click Add → găsește „OPCOM România" → Install
  6. Restartează Home Assistant

Manual

  1. Copiază folderul custom_components/opcom/ în directorul config/custom_components/ din Home Assistant
  2. Restartează Home Assistant

Configurare

Pasul 1 — Adaugă integrarea

  1. SettingsDevices & ServicesAdd Integration
  2. Caută „OPCOM" sau „OPCOM România"
  3. Completează formularul:
Câmp Descriere Implicit Interval permis
Limbă Limba exportului CSV (ro sau en) ro ro, en
Rezoluții Rezoluțiile în minute, separate prin virgulă 15,30,60 Oricare din: 15, 30, 60
Zile în avans Câte zile să descarce (1 = doar azi, 2 = azi + mâine) 2 1–3
Interval actualizare La câte minute să reîmprospăteze datele 15 5–180 minute
Fereastră planificare Durata ferestrei de preț optim (în minute) 60 minim 15 minute
Număr ferestre Câte ferestre optime să calculeze (top N) — ore acoperite = N × fereastră ÷ 60 6 1–24

Pasul 2 — Reconfigurare (opțional)

Toate setările pot fi modificate după instalare, fără a șterge integrarea:

  1. SettingsDevices & Services → click pe integrarea OPCOM
  2. Click pe Configure (⚙️)
  3. Modifică setările dorite → Submit
  4. Integrarea se reîncarcă automat cu noile setări

Entități create

Integrarea creează un device numit „OPCOM România". Sub el, pentru fiecare rezoluție configurată, se creează 10 entități (8 senzori + 2 senzori binari).

Cu configurarea implicită (3 rezoluții: 15, 30, 60) = 30 entități total.

Senzori de preț

Entitate Descriere Unitate Exemplu
[15] Preț acum Prețul energiei în intervalul curent RON/MWh 322.56
[15] Preț următor Prețul energiei în intervalul următor RON/MWh 256.51

Atribute:

data: "2026-02-21"
rezolutie: "PT15M"
interval: 45
ora: "11:00 → 11:15"
zona: "Romania"

Senzori ferestre optime (azi + mâine)

Entitate Descriere Unitate
[15] Cea mai ieftină fereastră azi Prețul mediu al celei mai ieftine ferestre din ziua curentă RON/MWh
[15] Cea mai scumpă fereastră azi Prețul mediu al celei mai scumpe ferestre din ziua curentă RON/MWh
[15] Cea mai ieftină fereastră mâine La fel, pentru ziua următoare (Necunoscut până la publicare) RON/MWh
[15] Cea mai scumpă fereastră mâine La fel, pentru ziua următoare RON/MWh

Cum funcționează:

Senzorul afișează ca valoare principală (state) prețul mediu al celei mai bune ferestre. În atribute, sunt listate toate top N ferestrele, sortate după preț.

Ferestrele sunt non-suprapuse: algoritmul greedy alege cea mai bună fereastră, marchează acele intervale ca „ocupate", apoi caută următoarea cea mai bună din cele rămase. Asta garantează că fiecare fereastră acoperă ore diferite.

Ferestrele zilei includ și intervale deja trecute — sunt afișate ca referință istorică.

Atribute:

data: "2026-02-21"
rezolutie: "PT15M"
fereastra_minute: 60
numar_ferestre: 6
ferestre:
  - ora: "00:00 → 01:00"
    pret_mediu: "295.43 RON/MWh"
    intervale: "1–4"
  - ora: "03:00 → 04:00"
    pret_mediu: "310.22 RON/MWh"
    intervale: "13–16"
  - ora: "02:00 → 03:00"
    pret_mediu: "318.50 RON/MWh"
    intervale: "9–12"

Senzori intervale rămase

Entitate Descriere Unitate
[15] Intervale rămase cumpărare azi Câte intervale ieftine mai rămân de acum încolo număr
[15] Intervale rămase vânzare azi Câte intervale scumpe mai rămân de acum încolo număr

Acești senzori arată câte intervale bune mai sunt în viitor. Valoarea scade natural spre 0 pe parcursul zilei, pe măsură ce intervalele trec.

Ferestrele sunt recalculate doar din intervale viitoare (min_interval = intervalul curent), deci nu iau în calcul ore deja trecute.

Atribute:

data: "2026-02-21"
rezolutie: "PT15M"
fereastra_minute: 60
numar_ferestre: 6
interval_curent: 45
intervale_ramase:
  - interval: 73
    ora: "18:00 → 18:15"
    pret: "580.20 RON/MWh"
  - interval: 74
    ora: "18:15 → 18:30"
    pret: "575.10 RON/MWh"

Senzori binari (pentru automatizări)

Entitate Descriere Pornit când...
[15] Ar trebui să încarce acum Indică dacă e momentul optim pentru încărcare (preț mic) Intervalul curent e într-o fereastră ieftină
[15] Ar trebui să exporte acum Indică dacă e momentul optim pentru export/vânzare (preț mare) Intervalul curent e într-o fereastră scumpă

Comportament:

  • Calculează ferestrele doar din intervale viitoare (nu recomandă intervale deja trecute)
  • Folosește cross-day: combină datele de azi cu cele de mâine (dacă sunt disponibile). La ora 23:00, dacă mâine la 02:00 prețul e foarte mic, senzorul „ar trebui să încarce" va ține cont de asta
  • Ferestrele sunt non-suprapuse (algoritm greedy)

Atribute:

data: "2026-02-21"
rezolutie: "PT15M"
fereastra_minute: 60
numar_ferestre: 6
interval_curent: 45
fereastra_activa:
  ora: "11:00 → 12:00"
  pret_mediu: "322.56 RON/MWh"
  intervale: "45–48"

Când nu e activ (Oprit), fereastra_activa este null.


Prefixul de rezoluție

Toate entitățile au un prefix care indică rezoluția: [15], [30], sau [60].

  • [15] = PT15M — intervale de 15 minute (96 pe zi). Cel mai granular. Disponibil doar pe OPCOM pentru anumite piețe.
  • [30] = PT30M — intervale de 30 minute (48 pe zi).
  • [60] = PT60M — intervale de 60 minute (24 pe zi). Cel mai comun.

Poți configura una, două, sau toate trei rezoluțiile. Dacă nu ai nevoie de granularitate, folosește doar 60.


Algoritmul de ferestre

Cum funcționează

  1. Sliding window: pentru fiecare poziție posibilă în ziua respectivă, se calculează media prețurilor pe durata ferestrei (ex: 4 intervale × 15 min = 60 min)
  2. Sortare: toate candidatele sunt sortate crescător (pentru ieftin) sau descrescător (pentru scump)
  3. Selecție greedy non-suprapusă: se alege cea mai bună fereastră, se marchează intervalele ca ocupate, apoi se alege următoarea cea mai bună care NU se suprapune cu cele deja selectate. Se repetă până se ating top N ferestre.

Exemplu concret

Cu rezoluție PT15M și fereastră de 60 minute (4 sloturi), pentru o zi cu 96 intervale:

  • Se generează 93 de candidați (sliding window: 1–4, 2–5, ..., 93–96)
  • Se sortează după preț mediu
  • Se alege cea mai ieftină (ex: sloturi 1–4, medie 295 RON)
  • Se marchează 1, 2, 3, 4 ca ocupate
  • Orice candidat care include 1, 2, 3, sau 4 e eliminat
  • Se alege următoarea (ex: sloturi 13–16, medie 310 RON)
  • Se repetă până la top N (implicit 6)

Rezultat: 6 ferestre distincte temporal, fără suprapunere.

Filtrarea intervalelor trecute

Senzorii binari și senzorii de intervale rămase primesc un parametru min_interval egal cu intervalul curent. Toate ferestrele care încep înainte de acest interval sunt eliminate din candidați. Astfel:

  • La ora 14:00, nu ți se recomandă să „încarci" la 03:00 (deja trecut)
  • Ferestrele se recalculează dinamic pe măsură ce trece ziua

Senzorii de ferestre (WindowsSensor) nu filtrează — arată toate ferestrele zilei ca referință.

Cross-day (senzorii binari)

La ora 23:00, senzorii binari combină:

  • Intervalele rămase din azi (ex: 93–96 pentru PT15)
  • Toate intervalele de mâine (ex: 97–192, cu offset)

Astfel pot recomanda încărcarea la 02:00 mâine chiar dacă azi nu mai sunt ferestre bune. Funcționează doar dacă datele de mâine sunt disponibile (publicate de OPCOM, de obicei după ora 13:00).

Cum calculezi setările corect

Cele două setări window_minutes și top_n_windows lucrează împreună:

Ore acoperite = top_n_windows × window_minutes ÷ 60

Aceeași formulă se aplică identic pe toate rezoluțiile (PT15, PT30, PT60). Integrarea nu diferențiază per rezoluție.

Exemplu: ai nevoie de 4 ore de cumpărare/vânzare → window_minutes = 60, top_n_windows = 4 → 4 × 60 ÷ 60 = 4 ore.

⚠️ Atenție: dacă top_n_windows e prea mare, senzorii de cumpărare ȘI vânzare se activează simultan. Cu top_n = 16 și window_minutes = 60: 16 ore „ieftine" + 16 ore „scumpe" = 32, dar ziua are 24 → minim 8 ore se suprapun.

Regulă practică: top_n × window_minutes ÷ 60 nu ar trebui să depășească 8–10 ore. Detalii și tabel de referință în SETUP.md.


Exemplu de automatizare

Încarcă bateria când prețul e mic

automation:
  - alias: "Încarcă bateria la preț ieftin"
    trigger:
      - platform: state
        entity_id: binary_sensor.ar_trebui_sa_incarce_acum_pt15_azi
        to: "on"
    action:
      - service: switch.turn_on
        target:
          entity_id: switch.battery_charger

  - alias: "Oprește încărcarea când se termină fereastra ieftină"
    trigger:
      - platform: state
        entity_id: binary_sensor.ar_trebui_sa_incarce_acum_pt15_azi
        to: "off"
    action:
      - service: switch.turn_off
        target:
          entity_id: switch.battery_charger

Exportă energie când prețul e mare

automation:
  - alias: "Exportă la preț scump"
    trigger:
      - platform: state
        entity_id: binary_sensor.ar_trebui_sa_exporte_acum_pt15_azi
        to: "on"
    action:
      - service: switch.turn_on
        target:
          entity_id: switch.grid_export

Notificare când se publică prețurile de mâine

automation:
  - alias: "Prețuri mâine disponibile"
    trigger:
      - platform: state
        entity_id: sensor.cea_mai_ieftina_fereastra_maine_pt60_maine
        from: "unknown"
    action:
      - service: notify.mobile_app
        data:
          title: "OPCOM: Prețuri mâine"
          message: >
            Cea mai ieftină fereastră mâine:
            {{ state_attr('sensor.cea_mai_ieftina_fereastra_maine_pt60_maine', 'ferestre')[0].ora }}
            la {{ states('sensor.cea_mai_ieftina_fereastra_maine_pt60_maine') }} RON/MWh

Diagnostics

Integrarea expune date complete de diagnosticare prin mecanismul standard HA:

  1. SettingsDevices & Services → click pe OPCOM
  2. Click pe cele 3 puncte (⋮) → Download diagnostics

Fișierul JSON conține:

  • Configurația completă (data + options)
  • Lista device-urilor și entităților create
  • Toate datele raw descărcate de pe OPCOM (prețuri, volume, sumare)
  • Starea ultimei actualizări (succes/eroare)

Util la troubleshooting sau la raportarea unui bug.


Structura fișierelor

custom_components/opcom/
├── __init__.py          # Setup/unload integrare + update_listener
├── api.py               # Descărcare CSV + parsing OPCOM
├── binary_sensor.py     # Senzori binari (ar trebui să încarce/exporte)
├── config_flow.py       # Formularul de configurare + opțiuni
├── const.py             # Constante, defaults, OpcomSettings dataclass
├── coordinator.py       # DataUpdateCoordinator — fetch centralizat
├── diagnostics.py       # Export diagnostics
├── helpers.py           # Funcții comune (ferestre, formatare, cross-day)
├── manifest.json        # Metadata integrare
├── sensor.py            # Senzori (preț, ferestre, intervale rămase)
└── translations/
    ├── en/
    │   └── strings.json # Traduceri EN (config flow)
    └── ro/
        └── ro.json      # Traduceri RO (config flow)

Cerințe

  • Home Assistant 2024.1.0 sau mai nou
  • HACS (opțional, pentru instalare ușoară)
  • Acces la internet — integrarea descarcă date de pe opcom.ro

Nu necesită dependențe externe (nu instalează pachete pip/npm).


Limitări cunoscute

  1. Prețurile de mâine nu sunt disponibile imediat — OPCOM le publică de obicei între 13:00–15:00. Până atunci, senzorii „mâine" afișează „Necunoscut".

  2. O singură instanță — integrarea suportă o singură configurare. Dacă încerci să adaugi a doua, vei primi eroare „already configured".

  3. Rezoluția PT15M include date suplimentare — exportul CSV la 15 minute conține și coloane de volum tranzacționat + zonă. Rezoluțiile de 30 și 60 minute au doar preț. Asta vine de la OPCOM, nu de la integrare.

  4. Cross-day funcționează doar dacă datele de mâine există — dacă days_ahead este setat la 1, nu se descarcă datele de mâine și funcția cross-day nu are efect.


Autor

Ciprian Nicolae (@cnecrea)


Licență

MIT

About

OPCOM PZU România → senzori Home Assistant (PT15M/PT30M/PT60M), preț curent/următor, ferestre ieftin/scump (greedy), cross-day, diagnostics.

Topics

Resources

License

Stars

Watchers

Forks

Sponsor this project

Packages

 
 
 

Languages