Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Nuova API sito GME #42

Closed
moddroid94 opened this issue May 6, 2024 · 50 comments · Fixed by #71
Closed

Nuova API sito GME #42

moddroid94 opened this issue May 6, 2024 · 50 comments · Fixed by #71
Labels
enhancement New feature or request

Comments

@moddroid94
Copy link
Collaborator

Ciao, ho notato che e' online il nuovo sito di GME.
Il nuovo sito utilizza un endpoint API per scaricare il file zip, e ho pensato che si potesse semplificare la parte di download dal sito in quanto particolarmente convoluta.

Dopo un po' di tinkering sono riuscito a emulare una request che ci consente di scaricare lo zip senza fare scraping di valori sul sito con BeautifulSoup.

L'endpoint sembra essere di libero accesso, ovvero l'unico parametro che sembra essere importante per la request e' il referrer, che dev'essere la pagina di download del sito GME dov'e' situato il pulsante.

La request con la quale sono riuscito a scaricare lo zip e' la seguente:
Su Powershell

Invoke-WebRequest -UseBasicParsing -Uri "https://gme.mercatoelettrico.org/DesktopModules/GmeDownload/API/ExcelDownload/downloadzipfile?DataInizio=20240507&DataFine=20240507&Date=20240506&Mercato=MGP&Settore=Prezzi&FiltroDate=InizioFine" `
-WebSession $session `
-Headers @{
"authority"="gme.mercatoelettrico.org"
  "method"="GET"
  "path"="/DesktopModules/GmeDownload/API/ExcelDownload/downloadzipfile?DataInizio=20240507&DataFine=20240507&Date=20240506&Mercato=MGP&Settore=Prezzi&FiltroDate=InizioFine"
  "scheme"="https"
  "accept"="application/json, text/plain, */*"
  "accept-encoding"="gzip, deflate, br, zstd"
  "accept-language"="en-US,en;q=0.9"
  "cache-control"="no-cache"
  "dnt"="1"
  "moduleid"="12103"
  "pragma"="no-cache"
  "priority"="u=1, i"
  "referer"="https://gme.mercatoelettrico.org/en-us/Home/Results/Electricity/MGP/Download?valore=Prezzi"
  "sec-ch-ua"="`"Not-A.Brand`";v=`"99`", `"Chromium`";v=`"124`""
  "sec-ch-ua-mobile"="?0"
  "sec-ch-ua-platform"="`"Windows`""
  "sec-fetch-dest"="empty"
  "sec-fetch-mode"="cors"
  "sec-fetch-site"="same-origin"
  "tabid"="1749"
  "userid"="-1"
} 

Quando la richiesta viene effettuata dal browser, vi e' un campo aggiuntivo: requestverificationtoken.
Ma anche omettendo il token l'API sembra funzionare da terminale o codice.

Con python basta impostare gli headers di una request con i seguenti valori e puntare all'url con i parametri giusti.

Endpoint:
"https://gme.mercatoelettrico.org/DesktopModules/GmeDownload/API/ExcelDownload/downloadzipfile?DataInizio=20240507&DataFine=20240507&Date=20240506&Mercato=MGP&Settore=Prezzi&FiltroDate=InizioFine"

headers:

{
    "accept": "application/json, text/plain, */*",
    "accept-language": "en-US,en;q=0.9",
    "cache-control": "no-cache",
    "moduleid": "12103",
    "pragma": "no-cache",
    "priority": "u=1, i",
    "referrer": "https://gme.mercatoelettrico.org/en-us/Home/Results/Electricity/MGP/Download?valore=Prezzi",
    "sec-ch-ua": '"Not-A.Brand";v="99", "Chromium";v="124"',
    "sec-ch-ua-mobile": "?0",
    "sec-ch-ua-platform": '"Windows"',
    "sec-fetch-dest": "empty",
    "sec-fetch-mode": "cors",
    "sec-fetch-site": "same-origin",
    "tabid": "1749",
    "userid": "-1",
}

Non so se e' un problema di auth da parte loro o se e' inteso per essere pubblico, ad ogni modo anche dovessimo recuperare il token dai cookie/response dovrebbe essere decisamente piu' comodo.

PS. Ho forkato la repo e sto facendo un po' di clean up / spostamento di classi nei rispettivi moduli cosi' da seguire meglio le linee guida per le integrazioni di HA e rendere il codice un po' piu' leggibile, e possibilmente rendere piu' semplice l'adattamento ad un cambiamento come quello descritto qua #38

Se vuoi intanto dare un occhiata puoi trovarla tra le mie repo, non appena avro' testato le modifiche faccio una draft per una PR cosi da poter vedere insieme i cambiamenti.

@virtualdj
Copy link
Owner

Ciao, ho notato che e' online il nuovo sito di GME.

Ciao, non l'avevo notato... certo che sono riusciti a fare uno pure peggio del precedente....

Il nuovo sito utilizza un endpoint API per scaricare il file zip, e ho pensato che si potesse semplificare la parte di download dal sito in quanto particolarmente convoluta.

Almeno questo sì è migliorato.

Dopo un po' di tinkering sono riuscito a emulare una request che ci consente di scaricare lo zip senza fare scraping di valori sul sito con BeautifulSoup.

Molto bene, di là (sul vecchio) non c'ero riuscito.

Quando la richiesta viene effettuata dal browser, vi e' un campo aggiuntivo: requestverificationtoken. Ma anche omettendo il token l'API sembra funzionare da terminale o codice.

Da browser c'ho messo un bel po' a ritrovare il link (QUESTO) da dove scaricare lo ZIP. Per fortuna non hanno cambiato il formato interno.

PS. Ho forkato la repo e sto facendo un po' di clean up / spostamento di classi nei rispettivi moduli cosi' da seguire meglio le linee guida per le integrazioni di HA e rendere il codice un po' piu' leggibile,

Ho visto, purtroppo io non sono del mestiere 😉 ma più un hobbista, quindi mi sono arrangiato un po' con Google per risolvere il problema (no IA).

I match case ad esempio li avevo evitati perché mi sembravano meno leggibili... 😮 però effettivamente mi pare che la tua versione vada molto bene. Il chaining degli operatori ((a and b) > 0) invece ignoravo proprio esistesse!

Vabbè, sono qui per imparare!

e possibilmente rendere piu' semplice l'adattamento ad un cambiamento come quello descritto qua #38

Intendi il discorso che facevo sotto del calcolo del totale della bolletta (sperando che nel frattempo non ci cambino il PUN)?

non appena avro' testato le modifiche faccio una draft per una PR cosi da poter vedere insieme i cambiamenti.

Certamente, grazie!

@virtualdj virtualdj added the enhancement New feature or request label May 6, 2024
@moddroid94
Copy link
Collaborator Author

Ciao @virtualdj ,

Per quanto riguarda le API si avevo provato anche io con la tua repo in locale ma era troppo complicato usare bs4, per quanto hobbista hai escogitato un metodo non banale per emulare quel download! 👌

Ad ogni modo si i match li ho usati con parsimonia perche' comunque prediligo la leggibilita' del codice alla pura performance, ma dove si puo 😁

Per il futuro intendevo sia l'integrazione della bolletta, che ho "simulato" anche io con helper & Co. e vorrei aiutare a integrare, e sia per quanto riguarda la questione delle zonali, che sul sito nuovo sembra oltretutto essere gia' disponibile, anche se non ho capito assolutamente nulla di come funzioni 😂

Comunque ho testato il fork e sembra funzionare, magari proviamo a farlo girare un paio di giorni, magari anche su qualche altra istanza giusto per sicurezza, ho fatto altre due modifiche che ora committo e per ora lo sto facendo girare su docker e ha recuperato zip e settato tutto correttamente.

@virtualdj
Copy link
Owner

virtualdj commented May 7, 2024

Comunque giusto per provare ho buttato su sulla seconda istanza Docker il tuo fork e c'è qualcosa che non va sul calcolo delle fasce.

Dal log vedo questo:

2024-05-07 23:28:22.988 WARNING (SyncWorker_3) [homeassistant.loader] We found a custom integration pun_sensor which has not been tested by Home Assistant. This component might cause stability problems, be sure to disable it if you experience issues with Home Assistant
2024-05-07 23:28:30.576 DEBUG (MainThread) [custom_components.pun_sensor.coordinator] Coordinator inizializzato (con 'usa dati reali' = False).
2024-05-07 23:28:30.577 DEBUG (MainThread) [custom_components.pun_sensor.coordinator] Ora corrente sistema: Tue 07/05/2024 23:28:30 +0200
2024-05-07 23:28:30.577 DEBUG (MainThread) [custom_components.pun_sensor.coordinator] Ora corrente fuso orario italiano: Tue 07/05/2024 23:28:30 +0200
2024-05-07 23:28:30.579 INFO (MainThread) [custom_components.pun_sensor.coordinator] Nuova fascia corrente: F1 (prossima: Tue 07/05/2024 19:00:00 +0200)
2024-05-07 23:28:30.579 DEBUG (MainThread) [custom_components.pun_sensor.coordinator] Manually updated pun_sensor data
2024-05-07 23:28:30.579 DEBUG (MainThread) [custom_components.pun_sensor.coordinator] Ora corrente sistema: Tue 07/05/2024 23:28:30 +0200
2024-05-07 23:28:30.580 DEBUG (MainThread) [custom_components.pun_sensor.coordinator] Ora corrente fuso orario italiano: Tue 07/05/2024 23:28:30 +0200
2024-05-07 23:28:30.581 INFO (MainThread) [custom_components.pun_sensor.coordinator] Nuova fascia corrente: F1 (prossima: Tue 07/05/2024 19:00:00 +0200)
2024-05-07 23:28:30.581 DEBUG (MainThread) [custom_components.pun_sensor.coordinator] Manually updated pun_sensor data
2024-05-07 23:28:30.582 DEBUG (MainThread) [custom_components.pun_sensor.coordinator] Ora corrente sistema: Tue 07/05/2024 23:28:30 +0200
2024-05-07 23:28:30.582 DEBUG (MainThread) [custom_components.pun_sensor.coordinator] Ora corrente fuso orario italiano: Tue 07/05/2024 23:28:30 +0200
2024-05-07 23:28:30.583 INFO (MainThread) [custom_components.pun_sensor.coordinator] Nuova fascia corrente: F1 (prossima: Tue 07/05/2024 19:00:00 +0200)
...

Come vedi sbaglia a calcolare la prossima fascia (la mette nel passato) e questo causa un loop continuo che blocca tutto.
Ora però non riesco a fare il debug, sono troppo stanco dalla giornata 😪

@moddroid94
Copy link
Collaborator Author

Si avevo notato 😂

Mi era fatto prendere la mano con quei comparison e ne ho messo uno che non poteva ritornare vero nemmeno se pregavo 🤣

In teoria ho fixato tutto, quando poi hai tempo puoi provare ad aggiornarlo da hacs :)

@g1za
Copy link
Contributor

g1za commented May 8, 2024

Scusate se mi intrometto ma vorrei seguire la discussione perché avendomi fatto scoprire che il sito è cambiato ho paura che prima o poi dovrò rimettere mano al codice per scaricare i prezzi zonali, che avevo realizzato con il componente multiscrape, e in questa discussione vedo la possibilità di trarre spunti utili.

Se posso dare il mio piccolo contributo (ne so mooooolto meno di voi), se utile e non indiscreto, credo che l'endpoint per accedere ai prezzi zonali in XML sia il seguente
https://gme.mercatoelettrico.org/DesktopModules/GmeEsitiPrezziME/API/item/GetMEPrezzi?DataInizio=20240509&DataFine=20240509&Granularita=h&Mercato=MGP&Zona=NORD&Tipologia=PrezziZonali

Ovviamente usato così nudo e crudo non funziona, restituisce un errore, ma non se se è una problematica di referrer come menzionato sopra, o di cookie (tramite l'accettazione delle condizioni di uso nella videata che ora è un pop-up).

Pagina web con i prezzi zonali:
https://gme.mercatoelettrico.org/it-it/Home/Esiti/Elettricita/MGP/Esiti/PrezziZonali#IntestazioneGrafico

@virtualdj
Copy link
Owner

Se posso dare il mio piccolo contributo (ne so mooooolto meno di voi), se utile e non indiscreto, credo che l'endpoint per accedere ai prezzi zonali in XML sia il seguente
https://gme.mercatoelettrico.org/DesktopModules/GmeEsitiPrezziME/API/item/GetMEPrezzi?DataInizio=20240509&DataFine=20240509&Granularita=h&Mercato=MGP&Zona=NORD&Tipologia=PrezziZonali

Domanda, visto che non me ne intendo invece di prezzi zonali... ma questi non sono dentro nel file XML che scarica già l'integrazione come ZIP (uno XML per ogni giorno)?

Ogni ora dell'XML ha questi dati:

  <Prezzi>
    <Data>20240509</Data>
    <Mercato>MGP</Mercato>
    <Ora>1</Ora>
    <PUN>94,320000</PUN>
    <NAT>94,320000</NAT>
    <CALA>94,320000</CALA>
    <CNOR>94,320000</CNOR>
    <CSUD>94,320000</CSUD>
    <NORD>94,320000</NORD>
    <SARD>94,320000</SARD>
    <SICI>94,320000</SICI>
    <SUD>94,320000</SUD>
    <AUST>94,320000</AUST>
    <COAC>94,320000</COAC>
    <COUP>94,320000</COUP>
    <CORS>94,320000</CORS>
    <FRAN>94,320000</FRAN>
    <GREC>94,320000</GREC>
    <SLOV>94,320000</SLOV>
    <SVIZ>94,320000</SVIZ>
    <BSP>94,320000</BSP>
    <MALT>94,320000</MALT>
    <XAUS>94,320000</XAUS>
    <XFRA>94,320000</XFRA>
    <MONT>94,320000</MONT>
    <XGRE>94,320000</XGRE>
  </Prezzi>

E noi di questi prendiamo solo il <PUN>94,320000</PUN>. A te quali servono? Immagino siano già qui...

@moddroid94
Copy link
Collaborator Author

Se posso dare il mio piccolo contributo (ne so mooooolto meno di voi), se utile e non indiscreto, credo che l'endpoint per accedere ai prezzi zonali in XML sia il seguente https://gme.mercatoelettrico.org/DesktopModules/GmeEsitiPrezziME/API/item/GetMEPrezzi?DataInizio=20240509&DataFine=20240509&Granularita=h&Mercato=MGP&Zona=NORD&Tipologia=PrezziZonali

Ovviamente usato così nudo e crudo non funziona, restituisce un errore, ma non se se è una problematica di referrer come menzionato sopra, o di cookie (tramite l'accettazione delle condizioni di uso nella videata che ora è un pop-up).

Ho testato la API e non funziona nemmeno con il referrer, pero' penso che potrebbe essere un API interna del sito, quell'item mi sembra una route di react. dove l'hai trovata? 😂

In compenso il pulsante che scarica l'excel con i dati sembra essere un endpoint pubblico, regolando la granularita' penso che si possano ottenere dati di un mese o piu', per l'estrazione dei dati probabilmente un excel e' anche meglio di un XML👌
https://gme.mercatoelettrico.org/DesktopModules/GmeEsitiPrezziME/API/ExcelDownload/download?DataInizio=20240509&DataFine=20240509&Granularita=h&Mercato=MGP&Zona=Nord&Tipologia=PrezziZonali

@g1za
Copy link
Contributor

g1za commented May 8, 2024

Domanda, visto che non me ne intendo invece di prezzi zonali... ma questi non sono dentro nel file XML che scarica già l'integrazione come ZIP (uno XML per ogni giorno)?

Ogni ora dell'XML ha questi dati:

  <Prezzi>
    <Data>20240509</Data>
    <Mercato>MGP</Mercato>
    <Ora>1</Ora>
    <PUN>94,320000</PUN>
    <NAT>94,320000</NAT>
    <CALA>94,320000</CALA>
    <CNOR>94,320000</CNOR>
    <CSUD>94,320000</CSUD>
    <NORD>94,320000</NORD>
    <SARD>94,320000</SARD>
    <SICI>94,320000</SICI>
    <SUD>94,320000</SUD>
    <AUST>94,320000</AUST>
    <COAC>94,320000</COAC>
    <COUP>94,320000</COUP>
    <CORS>94,320000</CORS>
    <FRAN>94,320000</FRAN>
    <GREC>94,320000</GREC>
    <SLOV>94,320000</SLOV>
    <SVIZ>94,320000</SVIZ>
    <BSP>94,320000</BSP>
    <MALT>94,320000</MALT>
    <XAUS>94,320000</XAUS>
    <XFRA>94,320000</XFRA>
    <MONT>94,320000</MONT>
    <XGRE>94,320000</XGRE>
  </Prezzi>

E noi di questi prendiamo solo il <PUN>94,320000</PUN>. A te quali servono? Immagino siano già qui...

Sono loro, allora il file zippato contiene già tutto.
Io utilizzo i prezzi zonali NORD, ma possono variare a seconda della zona geografica in cui ti trovi.
Per vostra informazione i dati zonali di un giorno vengono resi disponibili nel primo pomeriggio del giorno precedente, generalmente entro le 14-15. (per necessità mie io mi scarico sia quelli di oggi che quelli di domani - fintanto che quelli di domani mancano li sostituisco con quelli di oggi)

@g1za
Copy link
Contributor

g1za commented May 8, 2024

Ho testato la API e non funziona nemmeno con il referrer, pero' penso che potrebbe essere un API interna del sito, quell'item mi sembra una route di react. dove l'hai trovata? 😂

Con Firefox, analizzando la pagina, con l'inspector, nella sezione "rete" mostra le chiamate che vengono effettuate.
Selezionando poi questa chiamata GET specifica mostra pure l'header della chiamata e risposta. Magari copiando i paramentri dal browser riesci a replicarla con Powershell e capire se è un endpoint pubblico o meno.

In compenso il pulsante che scarica l'excel con i dati sembra essere un endpoint pubblico, regolando la granularita' penso che si possano ottenere dati di un mese o piu', per l'estrazione dei dati probabilmente un excel e' anche meglio di un XML👌 https://gme.mercatoelettrico.org/DesktopModules/GmeEsitiPrezziME/API/ExcelDownload/download?DataInizio=20240509&DataFine=20240509&Granularita=h&Mercato=MGP&Zona=Nord&Tipologia=PrezziZonali

Ho sempre cercato di non dover scaricare file in locale, ma probabilmente l'approccio è diverso/la necessità è differente quando si sviluppa un component per homeassistant.

Mannaggia a loro che nel vecchio sito hanno il pulsante per ottenere l'XML direttamente e qui invece è stato tolto :|

@moddroid94
Copy link
Collaborator Author

Ho testato la API e non funziona nemmeno con il referrer, pero' penso che potrebbe essere un API interna del sito, quell'item mi sembra una route di react. dove l'hai trovata? 😂

Con Firefox, analizzando la pagina, con l'inspector, nella sezione "rete" mostra le chiamate che vengono effettuate. Selezionando poi questa chiamata GET specifica mostra pure l'header della chiamata e risposta. Magari copiando i paramentri dal browser riesci a replicarla con Powershell e capire se è un endpoint pubblico o meno.

In compenso il pulsante che scarica l'excel con i dati sembra essere un endpoint pubblico, regolando la granularita' penso che si possano ottenere dati di un mese o piu', per l'estrazione dei dati probabilmente un excel e' anche meglio di un XML👌 https://gme.mercatoelettrico.org/DesktopModules/GmeEsitiPrezziME/API/ExcelDownload/download?DataInizio=20240509&DataFine=20240509&Granularita=h&Mercato=MGP&Zona=Nord&Tipologia=PrezziZonali

Ho sempre cercato di non dover scaricare file in locale, ma probabilmente l'approccio è diverso/la necessità è differente quando si sviluppa un component per homeassistant.

Mannaggia a loro che nel vecchio sito hanno il pulsante per ottenere l'XML direttamente e qui invece è stato tolto :|

sisi ma ho provato da powershell con referrer e mi restituisce errore di auth, per quello penso sia interna, sicuramente non e' pubblica 😂
In ogni caso se nel file attuale abbiamo gia' i valori non penso che questa serva

l'excel in realta' si potrebbe caricare in memoria direttamente quindi non sarebbe comunque un problema :)

@virtualdj
Copy link
Owner

l'excel in realta' si potrebbe caricare in memoria direttamente quindi non sarebbe comunque un problema :)

Ma è già così, in memoria, mica fa un file...
https://github.com/virtualdj/pun_sensor/blob/master/custom_components%2Fpun_sensor%2F__init__.py#L209-L211

@moddroid94
Copy link
Collaborator Author

l'excel in realta' si potrebbe caricare in memoria direttamente quindi non sarebbe comunque un problema :)

Ma è già così, in memoria, mica fa un file... https://github.com/virtualdj/pun_sensor/blob/master/custom_components%2Fpun_sensor%2F__init__.py#L209-L211

sisi lo so, era in risposta al commento di @g1za 😂

Ho sempre cercato di non dover scaricare file in locale, ma probabilmente l'approccio è diverso/la necessità è differente quando si sviluppa un component per homeassistant.

@virtualdj
Copy link
Owner

@moddroid94 Ah ok, il potrebbe mi ha tratto in inganno...

@Tagliax
Copy link

Tagliax commented Jul 17, 2024

Da qualche tempo riscontro un problema sul download dei dati:

2024-07-17 01:00:04.243 WARNING (MainThread) [custom_components.pun_sensor] Errore durante l'aggiornamento via web, nuovo tentativo tra 1 minuto.
Traceback (most recent call last):
  File "/config/custom_components/pun_sensor/__init__.py", line 335, in update_pun
    await self._async_update_data()
  File "/config/custom_components/pun_sensor/__init__.py", line 185, in _async_update_data
    viewstate = soup.find('input',{'name':'__VIEWSTATE'})['value']

@virtualdj
Copy link
Owner

virtualdj commented Jul 17, 2024

Da qualche tempo riscontro un problema sul download dei dati:

@Tagliax
Il fatto che usi soup.find significa che stai usando la versione "stabile" e non quella di questa issue (che è invece la beta).
Tuttavia non cambia: anch'io se guardo nei log vedo errori sporadici del genere, sia con la vecchia API (quella che ti dà problemi) che con la nuova (quella della beta).

Semplicemente, il sito fa abbastanza schifo e quindi capita che non risponda... Ma niente paura, se leggi bene i log vedrai che c'è il meccanismo di retry che raramente fallisce completamente. Prova a leggere sotto quella riga, se non ci sono altri warning significa che il successivo tentativo è andato a buon fine.

Quindi prendi il log per quello che è, un warning, che non pregiudica affatto il funzionamento dell'integrazione. Certo, si potrebbe silenziare, ma non credo abbia senso: io preferisco sapere se e quando il download fallisce.

@Tagliax
Copy link

Tagliax commented Jul 17, 2024

Ciao @virtualdj si ho notato i retry, ma anche quello di 1 ora sembra andare KO, ho preso il primo log.
Ho notato che ogni tanto fa le bizze l’endpoint…se è tutto nella norma, come non detto :)

@virtualdj
Copy link
Owner

virtualdj commented Jul 17, 2024

@Tagliax Nella norma per loro! Io direi che qualcosa lo dovrebbero pure sistemare 😄
Guarda qui sotto il mio log di stanotte:

2024-07-17 01:00:00.000 DEBUG (MainThread) [custom_components.pun_sensor] Connessione a URL login.
2024-07-17 01:00:04.502 WARNING (MainThread) [custom_components.pun_sensor] Errore durante l'aggiornamento via web, nuovo tentativo tra 1 minuto.
Traceback (most recent call last):
File "/config/custom_components/pun_sensor/__init__.py", line 330, in update_pun
await self._async_update_data()
File "/config/custom_components/pun_sensor/__init__.py", line 180, in _async_update_data
viewstate = soup.find('input',{'name':'__VIEWSTATE'})['value']
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^
TypeError: 'NoneType' object is not subscriptable
2024-07-17 01:01:04.638 DEBUG (MainThread) [custom_components.pun_sensor] Connessione a URL login.
2024-07-17 01:01:05.956 WARNING (MainThread) [custom_components.pun_sensor] Errore durante l'aggiornamento via web, nuovo tentativo tra 10 minuti.
Traceback (most recent call last):
File "/config/custom_components/pun_sensor/__init__.py", line 330, in update_pun
await self._async_update_data()
File "/config/custom_components/pun_sensor/__init__.py", line 180, in _async_update_data
viewstate = soup.find('input',{'name':'__VIEWSTATE'})['value']
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^
TypeError: 'NoneType' object is not subscriptable
2024-07-17 01:11:05.960 DEBUG (MainThread) [custom_components.pun_sensor] Connessione a URL login.
2024-07-17 01:11:07.562 WARNING (MainThread) [custom_components.pun_sensor] Errore durante l'aggiornamento via web, nuovo tentativo tra 60 minuti.
Traceback (most recent call last):
File "/config/custom_components/pun_sensor/__init__.py", line 330, in update_pun
await self._async_update_data()
File "/config/custom_components/pun_sensor/__init__.py", line 180, in _async_update_data
viewstate = soup.find('input',{'name':'__VIEWSTATE'})['value']
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^
TypeError: 'NoneType' object is not subscriptable
2024-07-17 02:11:07.566 DEBUG (MainThread) [custom_components.pun_sensor] Connessione a URL login.
2024-07-17 02:11:08.694 WARNING (MainThread) [custom_components.pun_sensor] Errore durante l'aggiornamento via web, nuovo tentativo tra 120 minuti.
Traceback (most recent call last):
File "/config/custom_components/pun_sensor/__init__.py", line 330, in update_pun
await self._async_update_data()
File "/config/custom_components/pun_sensor/__init__.py", line 180, in _async_update_data
viewstate = soup.find('input',{'name':'__VIEWSTATE'})['value']
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^
TypeError: 'NoneType' object is not subscriptable
2024-07-17 04:11:07.919 DEBUG (MainThread) [custom_components.pun_sensor] Connessione a URL login.
2024-07-17 04:11:10.967 DEBUG (MainThread) [custom_components.pun_sensor] Invio credenziali a URL login.
2024-07-17 04:11:18.977 DEBUG (MainThread) [custom_components.pun_sensor] Inizio download file ZIP con XML.
... cut ...

Come puoi leggere ha fallito il primo tentativo, quello dopo 1 minuto, quello dopo 10 minuti, quello dopo 60 minuti e quello dopo 120 minuti e dall'1 di notte siamo andati a finire alle 04:11! Però alla fine, alla sesta volta, ce l'ha fatta 😄

Vedi @moddroid94 che il sistema di retry fatto così aveva il suo perché? 🤣

@Tagliax
Copy link

Tagliax commented Jul 17, 2024

@virtualdj Io sospetto che loro in quel lasso di tempo eseguono operazioni di backup notturno, altrimenti non si spiegano questi down… 😅

@Tagliax
Copy link

Tagliax commented Sep 11, 2024

Ciao @virtualdj Avevi visto questa? https://gme.mercatoelettrico.org/it-it/Home/FTP

@virtualdj
Copy link
Owner

Avevi visto questa? https://gme.mercatoelettrico.org/it-it/Home/FTP

Mi pareva di averla notata, sì, quando si parlava del nuovo sito. Tecnicamente l'FTP c'era già prima, solo che non credo offra molti vantaggi... prima di tutto, tocca fare tutta quella trafila con "carte bollate" 😄 e poi mi pare molto più semplice pescare i dati giornalieri direttamente dall'endpoint HTTP, posto di aver spuntato le caselle di esonero responsabilità.

@Tagliax
Copy link

Tagliax commented Sep 11, 2024

Tecnicamente l'FTP c'era già prima, solo che non credo offra molti vantaggi...

L’ho segnalato perché ho l’impressione che poi tutto sarà sul nuovo sito e spegneranno il vecchio.
Magari c’è il modo di adattare già sul nuovo lo stesso metodo con endpoint HTTP

@virtualdj
Copy link
Owner

Magari c’è il modo di adattare già sul nuovo lo stesso metodo con endpoint HTTP

È già stato fatto nella PR #45 solo che non l'ho ancora unita perché stavo aspettando che l'autore sistemasse le rifiniture al codice.

È disponibile in "alfa" nella pre-release 0.9.1 (sì, antecedente all'ultima proprio perché bisognava sistemare il codice). Purtroppo in questo momento non ho il tempo sufficiente per dedicarmi a questo progetto, ma fintanto che funziona teniamo duro.

Appena possibile sistemerò tutto, ma mi serve tempo e calma.

@Tagliax
Copy link

Tagliax commented Sep 12, 2024

È già stato fatto nella PR #45 solo che non l'ho ancora unita perché stavo aspettando che l'autore sistemasse le rifiniture al codice.

Allora perfetto! :) ottimo così!
Grazie!

@MicheleMercuri
Copy link

MicheleMercuri commented Oct 3, 2024

l'excel in realta' si potrebbe caricare in memoria direttamente quindi non sarebbe comunque un problema :)

Ma è già così, in memoria, mica fa un file... https://github.com/virtualdj/pun_sensor/blob/master/custom_components%2Fpun_sensor%2F__init__.py#L209-L211

sisi lo so, era in risposta al commento di @g1za 😂

Ho sempre cercato di non dover scaricare file in locale, ma probabilmente l'approccio è diverso/la necessità è differente quando si sviluppa un component per homeassistant.

forse si potrebbe impostare un selettore all'interno dell'integrazione in modo che l'utente scelga il prezzo zonale orario della zona di mercato elettrico in cui è connesso l'impianto fotovoltaico :) e quindi lo script lo vada a leggere dall'xml già scaricato ed impostare nel sensore del "prezzo zonale orario". Io fino ad oggi l'ho fatto con multiscrape ma ormai il sito è andato e non ho tempo (e forse non saprei nemmeno come :( ) di rifare tutto con il sito che in ogni caso andrà avanti fino a dicembre 2024 :(, il lavoro nell'integrazione invece è già fatto o quasi :), il problema maggiore è che avremmo da n. 0 a 23 prezzi orari (n. 24 prezzi in totale) e non più uno come nel caso del PUN quindi dovrebbero essere inviati al sensore con il tempo giusto per aggiornare lo stato ogni ora (io facevo così con un trigger), HA non permette di creare stati "futuri" quindi il sensore del prezzo zonale orario per le successive 24 ore credo sia impossibile da fare dato che i prezzi del "giorno dopo" vengono pubblicati intorno alle 14 del giorno precedente. il prezzo zonale sarebbe utile da indicare in plancia energia per il rendimento del fotovoltaico e per avere un'idea del prezzo dell'energia immessa durante il giorno (io facevo anche una tabella con le 24 ore con un valore per ogni sensore del "giorno dopo" per sopperire all'impossibilità di avere un sensore con "stati futuri :) mentre per il prezzo zonale del giorno corrente non ci sarebbero problemi.

@g1za
Copy link
Contributor

g1za commented Oct 3, 2024

@MicheleMercuri per un fix veloce valido fino al 31/12 basta che aggiorni le resources del multiscrape come indicato qui

Se il prezzo zonale non verrà implementato nella nuova versione del componente (alla fine non ho capito se sta venendo valutata come possibilità) un'opzione è usare il portale ENTSO-E e appoggiarsi alle loro API (bisogna richiedere accesso), a meno di non studiare come fare scraping dal novo sito GME (oppure farsi una fork di questo progetto e riadattarla per i prezzi zonali).

@MicheleMercuri
Copy link

Ok grazie, proverò ad aggiornare. Ho provato a fare uno scarpe sul nuovo sito del gme ma non è possibile selezionare le zone di mercato elettrico, non è nemmeno possibile effettuare il download del file xml (sarebbe la cosa migliore) con tutti i dati perché mi rifiuta la connessione (ho provato velocemente con uno script in ha ma nisba) ho provato anche con uno script in una pagina HTML e nemmeno così ne vuole sapere, credo sia un problema di autorizzazione che non credo sia facile superare.

@virtualdj
Copy link
Owner

@g1za

alla fine non ho capito se sta venendo valutata come possibilità

Non era nei miei piani perché principalmente non lo uso e non so come funziona.
Ma, dato che alla fine quei prezzi ci sono già nel file XML che viene scaricato, estrarli non è un problema!
Solo vorrei capire - non me ne intendo - come poi li utilizzereste.

Supponiamo ad esempio che io imposti l'ora di download alle 16. Se oggi è il 3/10, alle 16 scarico l'XML e poi tengo in memoria i prezzi delle 24 ore relative al giorno 4/10 (cioè il successivo). Il 4/10, ogni ora, aggiorno il valore di un sensore (es. "Prezzo zonale") con quello tenuto in memoria nel precedente download per quell'ora. È questo quello che state chiedendo?

@MicheleMercuri
Copy link

Solo vorrei capire - non me ne intendo - come poi li utilizzereste.

Il prezzo zonale orario è il prezzo con cui viene remunerata l'energia immessa in rete (da un impianto fotovoltaico), per chi ha un contratto RID (ritiro dedicato) con il GSE. L'energia immessa in rete ogni ora (-10% di perdite di rete) viene moltiplicata per il prezzo zonale orario = prezzo al quale verrà pagata l'energia immessa (- tassazione Irpef).
Io faccio così (cioè facevo visto che tra poco non funzionerà più 😁): il 03/10/2024 alle 16:00 scarico i prezzi del giorno dopo dal gme es del 04/10/2024, con un trigger dalle ore 00:00 del 04/10/2024 ogni ora aggiorno un sensore con nello stato il prezzo zonale dell'ora di riferimento, con un utility Meter mi calcolo l'energia immessa ogni ora, alla fine:
Sensor.gme.prezzozonale * sensor.kwh.immessi = guadagno prima delle imposte da fotovoltaico 😁 (per essere precisi tolgo il 10% di perdite di rete).
Volendo il sensore del prezzo zonale può andare anche in plancia energia dato che lo prevede HA di default.
Spero si capisca 😁.

@g1za
Copy link
Contributor

g1za commented Oct 3, 2024

Premetto che conosco la tua posizione, che hai espresso anche in passato e che non posso chiedere nulla oltre a quanto stai già facendo (utilissimo e comodissimo peraltro). Sono conscio dell'impegno che lo sviluppo comporta, quindi accetto tutto quello che verrà prodotto. :)
Stavo giusto vedendo che direzione decidete di prendere con lo sviluppo per capire io come muovermi di conseguenza visto che in seguito ad un paio di commenti che avevo letto non mi era più chiaro.

Detto ciò...

Il prezzo zonale è alla base del calcolo della remunerazione su base oraria dell'energia prodotta dagli impianti fotovoltaici privati ed immessa in rete. In realtà per il Ritiro Dedicato (RID - per lo scambio sul posto SSP è differente e più complicato con prezzi definiti dall'autorità) ci sono dei conti e formule dietro da fare che nemmeno ricordo più ma restiamo sul facile senza scendere in dettagli. Il valore è differente per area geografica, da cui "prezzi zonali".

Sicuramente il caso d'uso più semplice è inserire questo dato nella dashboard di homeassistant per farsi calcolare o stimare il valore monetario dell'energia venduta.

Io personalmente utilizzo un addon (EMHASS) che in base a consumi previsti, costo di acquisto dell'energia, prezzo di vendita (prezzo zonale) e previsione di produzione fotovoltaica ottimizza la gestione energetica dell'abitazione permettendoti di comandare acquisto/vendita da/alla rete, carica/scarica batterie, accensione/spegnimento di carichi variabili. Il tutto per massimizzando una funzione di autoconsumo o profitto. Per questo add-on io utilizzo i prezzi zonali di oggi e di domani (appena resi disponibili, di solito fra le 14 e le 15, altrimenti continuo ad usare quelli di oggi), in quanto faccio fare l'elaborazione su 24h rolling.

Spero di essere stato esauriente e sufficientemente chiaro, altrimenti chiedimi pure.

@virtualdj
Copy link
Owner

@MicheleMercuri

Sensor.gme.prezzozonale * sensor.kwh.immessi = guadagno prima delle imposte da fotovoltaico 😁 (per essere precisi tolgo il 10% di perdite di rete)

Quindi sarebbe opportuno esporre direttamente PrezzoZonale * 0.9 nel valore del sensore, per tenere in considerazione le perdite di rete?

@g1za

Per questo add-on io utilizzo i prezzi zonali di oggi e di domani (appena resi disponibili, di solito fra le 14 e le 15, altrimenti continuo ad usare quelli di oggi)

Cioè intendi dire che se non sono disponibili domani userai i prezzi di oggi?

Premetto che conosco la tua posizione

Intanto mi basta capire il concetto, poi appena potrò lo implementerò.
Se adesso non fossi preso per il collo l'avrei già fatto 😄

@g1za
Copy link
Contributor

g1za commented Oct 4, 2024

Quindi sarebbe opportuno esporre direttamente PrezzoZonale * 0.9 nel valore del sensore, per tenere in considerazione le perdite di rete?

Se posso io direi che sarebbe più opportuno recuperare il dato grezzo e poi lasciare all'utente la responsabilità di utilizzarlo nel modo corretto o come più preferisce.

Cioè intendi dire che se non sono disponibili domani userai i prezzi di oggi?

Per forza, altrimenti l'elaborazione si blocca, avendo io sempre bisogno di 24h di dati. Quelli di oggi sono una buona approssimazione (anche l'unica) di quelli di domani e comunque nel mio caso l'impatto è limitato dal fatto che l'elaborazione è in là nel tempo oltre il cambio di data. Quindi quando sarò effettivamente al punto di aver bisogno di una previsione precisa (a quel punto a breve termine) oramai i dati effettivi per la giornata saranno già stati resi disponibili.

EDIT: no intendo che io ho bisogno di 24h di dati (fra dati reali e previsioni/dati futuri). I dati di domani saranno sicuramente disponibili ma solo dopo le 14-15 di oggi. Fino ad allora, avendo comunque sempre bisogno di 24h di dati (uso una finestra di 24h rolling), utilizzo i prezzi zonali (ma anche i PUN a dirla tutta) di oggi in quanto ne sono una buona approssimazione (anche l'unica). Nel mio caso l'impatto è limitato dal fatto che l'elaborazione è in là nel tempo, oltre il cambio di data. Quindi quando sarò effettivamente al punto di aver bisogno di una elaborazione precisa con dati reali (un'elaborazione a breve termine) oramai i dati effettivi per la giornata saranno già stati resi disponibili (saranno oramai già trascorse le 14-15).

@MicheleMercuri
Copy link

MicheleMercuri commented Oct 4, 2024

@MicheleMercuri

Sensor.gme.prezzozonale * sensor.kwh.immessi = guadagno prima delle imposte da fotovoltaico 😁 (per essere precisi tolgo il 10% di perdite di rete)

Quindi sarebbe opportuno esporre direttamente PrezzoZonale * 0.9 nel valore del sensore, per tenere in considerazione le perdite di rete?

il prezzo zonale orario pubblicato dal GME dalle 14:00 del giorno corrente in poi lo utilizzo dalla mezzanotte del giorno successivo moltiplicandolo per l'energia immessa nell'ora di riferimento calcolata con utility meter orario di HA, mai accaduto che non venisse pubblicato :).

perchè il GME pubblica con un giorno di anticipo il prezzo dell'energia oraria, quindi devo per forza usare il giorno successivo quella pubblicata alle 14:00 del giorno corrente (spero di essere riuscito a spiegarmi :) )

ho ricontrollato i calcoli fatti dal GSE per il RID (in RID ci sono gli impianti al 110% e gli impianti oltre i 20 kW e da non sottovalutare le comunità energetiche perché incompatibili con lo scambio sul posto-SSP)

la formula per il calcolo del prezzo di vendita è la seguente: energia * coeff_perd * prz_ora

con
energia = kWh immessi nell'ora di riferimento
coeff_perd = 1,052
prz_ora = prezzo zonale orario GME nell'ora di rif.

le perdite vengono sommate e non tolte (ho sbagliato a scrivere perchè mi sono confuso con il prezzo di acquisto dell'energia :))

ecco gli screen a prova della correttezza dei calcoli che ti ho illustrato e dei corrispettivi pagati per l'energia immessa dal mio impianto:

questo lo screen da sito GME dell'ora 14 e 15 zona immissione calabria del prezzo zonale orario:
Screenshot 2024-10-04 203643

questo è il foglio di calcolo che scarico dal sito del GSE con i dettagli delle cifre che avrò dal GSE, l'ora 14 e 15 corrispondono alle 13 e alle 14 perchè il sito del GME nella tabella inizia dall'ora 1 a contare le ore dalla mezzanotte :)
Screenshot 2024-10-04 203812

questo è l'importo che mi verrà pagato per agosto 2024 (ho optato per la liquidazione mensile senza il minimo garantito, perchè tanto è 0,04€/kWh e mi verrebbe pagato dopo quasi 6 mesi dalla fine dell'anno di riferimento, e perché immetto poco in quanto ho una Tesla e riesco a consumare gran parte degli 8.000 kWh prodotti :)
Screenshot 2024-10-04 204113

e questo è la prova sommando le celle del calcolo dell'energia immessa sul foglio di excel con il dettaglio orario:
Screenshot 2024-10-04 204150

spero si capisca tutto :)

@virtualdj virtualdj mentioned this issue Oct 5, 2024
@andbad
Copy link

andbad commented Oct 16, 2024

Interessante, sono riuscito a fare questa cosa dopo mesi di studio (l'ostacolo principale è stato il cookie...).
Più che altro mi serviva per decidere quando immettere da batteria (ovvero i picchi del prezzo zonale), ma stavo cercando di calcolare anche il valore di immissione per inserirlo nella plancia energia.
Non so a che punto si arrivato, ma lascio il mio script se può essere utile (lo so, il mio codice non è molto elegante):

#!/bin/bash
curl -b cookie.txt -c cookie.txt "https://www.mercatoelettrico.org/it-it/" > /dev/null
COOKIE=$(sed 's/Token\t/\n/;s/.*\n//' cookie.txt | cut -d '#' -f 1 | sed '/^$/d')
#echo "COOKIE: "$COOKIE
DATE=$(date '+%Y%m%d')
DATE="https://www.mercatoelettrico.org/DesktopModules/GmeEsitiPrezziME/API/ExcelDownload/download?DataInizio=$DATE&DataFine=$DATE&Granularita=h&Mercato=MGP&Zona=CNOR&Tipologia=PrezziZonali&TutteZone=0"
#echo "DATA: |"$DATE"|"

curl $DATE \
  -H 'accept: application/json, text/plain, */*' \
  -H 'accept-language: it-IT,it;q=0.9,en-US;q=0.8,en;q=0.7,ja;q=0.6,de;q=0.5' \
  -H 'cookie: dnn_IsMobile=False; .ASPXANONYMOUS=7l2zAezlkn0_4uMxdZhXuDHWhRjLPhphzJgKUfOvJdykj0T8PHrWTTmwtCWzdEg6_UY9BlvM2TNdCeojqhrOVauwWwPOlwSvr3M-ln6zjiZPvF170; language=it-IT; __RequestVerificationToken=$>
  -H 'moduleid: 518' \
  -H 'priority: u=1, i' \
  -H 'referer: https://www.mercatoelettrico.org/it-it/Home/Esiti/Elettricita/MGP/Esiti/PrezziZonali' \
  -H 'requestverificationtoken: $COOKIE' \
  -H 'sec-ch-ua: "Chromium";v="128", "Not;A=Brand";v="24", "Google Chrome";v="128"' \
  -H 'sec-ch-ua-mobile: ?0' \
  -H 'sec-ch-ua-platform: "Linux"' \
  -H 'sec-fetch-dest: empty' \
  -H 'sec-fetch-mode: cors' \
  -H 'sec-fetch-site: same-origin' \
  -H 'tabid: 55' \
  -H 'user-agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36' \
  -H 'userid: -1' --output gme.xlsx

rm cookie.txt -rf
mv gme.xlsx gme.zip
unzip gme.zip
mv  xl/worksheets/sheet1.xml ./gme.xml
rm _rels/ -rf
rm xl/ -rf
rm "[Content_Types].xml"
rm gme.zip
sed -e s/x://g -i gme.xml
sed -e s/,/./g -i gme.xml

mv gme.xml ./www/

file coockie.txt:

# Netscape HTTP Cookie File
# http://curl.haxx.se/rfc/cookie_spec.html
# This is a generated file!  Do not edit.

www.mercatoelettrico.org        FALSE   /       TRUE    0       ASP.NET_SessionId       5jojkem0y4imkuxrtenld1q0
www.mercatoelettrico.org        FALSE   /       TRUE    0       GmeItaliano     4EB33DD384A9C912E264E5A8A66C8F717AA6C36F38FA2FD4A26794FEAE846471F13E1D2787FD422E44A26058E8330EBD9E00C1171729909C66241D03A12E0750>

e questo lo yaml:

#/hass-config/packages/ict/gme.yaml
shell_command:
    gme: /home/andbad/.homeassistant/bash_scripts/gme.sh

rest:
  - scan_interval: 86400 #si aggiornano in automatico 1 volta al giorno, ma l'automazione forza l'aggiornamento dopo aver scaricato i dati.
    resource: https://192.168.0.2:8123/local/gme.xml
    verify_ssl: false
    sensor:
      - name: "GME 0-1"
        value_template: "{{ (value_json.worksheet.sheetData.row[1].c[2].v|float/1000)|round(3) }}"
        state_class: measurement
        unit_of_measurement: "€/kWh"
        json_attributes_path: "$.worksheet.sheetData.row[1].c[0]"
        json_attributes:
          - "v"
      - name: "GME 1-2"
        value_template: "{{ (value_json.worksheet.sheetData.row[2].c[2].v|float/1000)|round(3) }}"
        state_class: measurement
        unit_of_measurement: "€/kWh"
        json_attributes_path: "$.worksheet.sheetData.row[2].c[0]"
        json_attributes:
          - "v"
      - name: "GME 2-3"
        value_template: "{{ (value_json.worksheet.sheetData.row[3].c[2].v|float/1000)|round(3) }}"
        state_class: measurement
        unit_of_measurement: "€/kWh"
        json_attributes_path: "$.worksheet.sheetData.row[3].c[0]"
        json_attributes:
          - "v"
      - name: "GME 3-4"
        value_template: "{{ (value_json.worksheet.sheetData.row[4].c[2].v|float/1000)|round(3) }}"
        state_class: measurement
        unit_of_measurement: "€/kWh"
        json_attributes_path: "$.worksheet.sheetData.row[4].c[0]"
        json_attributes:
          - "v"
      - name: "GME 4-5"
        value_template: "{{ (value_json.worksheet.sheetData.row[5].c[2].v|float/1000)|round(3) }}"
        state_class: measurement
        unit_of_measurement: "€/kWh"
        json_attributes_path: "$.worksheet.sheetData.row[5].c[0]"
        json_attributes:
          - "v"
      - name: "GME 5-6"
        value_template: "{{ (value_json.worksheet.sheetData.row[6].c[2].v|float/1000)|round(3) }}"
        state_class: measurement
        unit_of_measurement: "€/kWh"
        json_attributes_path: "$.worksheet.sheetData.row[6].c[0]"
        json_attributes:
          - "v"
      - name: "GME 6-7"
        value_template: "{{ (value_json.worksheet.sheetData.row[7].c[2].v|float/1000)|round(3) }}"
        state_class: measurement
        unit_of_measurement: "€/kWh"
        json_attributes_path: "$.worksheet.sheetData.row[7].c[0]"
        json_attributes:
          - "v"
      - name: "GME 7-8"
        value_template: "{{ (value_json.worksheet.sheetData.row[8].c[2].v|float/1000)|round(3) }}"
        state_class: measurement
        unit_of_measurement: "€/kWh"
        json_attributes_path: "$.worksheet.sheetData.row[8].c[0]"
        json_attributes:
          - "v"
      - name: "GME 8-9"
        value_template: "{{ (value_json.worksheet.sheetData.row[9].c[2].v|float/1000)|round(3) }}"
        state_class: measurement
        unit_of_measurement: "€/kWh"
        json_attributes_path: "$.worksheet.sheetData.row[9].c[0]"
        json_attributes:
          - "v"
      - name: "GME 9-10"
        value_template: "{{ (value_json.worksheet.sheetData.row[10].c[2].v|float/1000)|round(3) }}"
        state_class: measurement
        unit_of_measurement: "€/kWh"
        json_attributes_path: "$.worksheet.sheetData.row[10].c[0]"
        json_attributes:
          - "v"
      - name: "GME 10-11"
        value_template: "{{ (value_json.worksheet.sheetData.row[11].c[2].v|float/1000)|round(3) }}"
        state_class: measurement
        unit_of_measurement: "€/kWh"
        json_attributes_path: "$.worksheet.sheetData.row[11].c[0]"
        json_attributes:
          - "v"
      - name: "GME 11-12"
        value_template: "{{ (value_json.worksheet.sheetData.row[12].c[2].v|float/1000)|round(3) }}"
        state_class: measurement
        unit_of_measurement: "€/kWh"
        json_attributes_path: "$.worksheet.sheetData.row[12].c[0]"
        json_attributes:
          - "v"
      - name: "GME 12-13"
        value_template: "{{ (value_json.worksheet.sheetData.row[13].c[2].v|float/1000)|round(3) }}"
        state_class: measurement
        unit_of_measurement: "€/kWh"
        json_attributes_path: "$.worksheet.sheetData.row[13].c[0]"
        json_attributes:
          - "v"
      - name: "GME 13-14"
        value_template: "{{ (value_json.worksheet.sheetData.row[14].c[2].v|float/1000)|round(3) }}"
        state_class: measurement
        unit_of_measurement: "€/kWh"
        json_attributes_path: "$.worksheet.sheetData.row[14].c[0]"
        json_attributes:
          - "v"
      - name: "GME 14-15"
        value_template: "{{ (value_json.worksheet.sheetData.row[15].c[2].v|float/1000)|round(3) }}"
        state_class: measurement
        unit_of_measurement: "€/kWh"
        json_attributes_path: "$.worksheet.sheetData.row[15].c[0]"
        json_attributes:
          - "v"
      - name: "GME 15-16"
        value_template: "{{ (value_json.worksheet.sheetData.row[16].c[2].v|float/1000)|round(3) }}"
        state_class: measurement
        unit_of_measurement: "€/kWh"
        json_attributes_path: "$.worksheet.sheetData.row[16].c[0]"
        json_attributes:
          - "v"
      - name: "GME 16-17"
        value_template: "{{ (value_json.worksheet.sheetData.row[17].c[2].v|float/1000)|round(3) }}"
        state_class: measurement
        unit_of_measurement: "€/kWh"
        json_attributes_path: "$.worksheet.sheetData.row[17].c[0]"
        json_attributes:
          - "v"
      - name: "GME 17-18"
        value_template: "{{ (value_json.worksheet.sheetData.row[18].c[2].v|float/1000)|round(3) }}"
        state_class: measurement
        unit_of_measurement: "€/kWh"
        json_attributes_path: "$.worksheet.sheetData.row[18].c[0]"
        json_attributes:
          - "v"
      - name: "GME 18-19"
        value_template: "{{ (value_json.worksheet.sheetData.row[19].c[2].v|float/1000)|round(3) }}"
        state_class: measurement
        unit_of_measurement: "€/kWh"
        json_attributes_path: "$.worksheet.sheetData.row[19].c[0]"
        json_attributes:
          - "v"
      - name: "GME 19-20"
        value_template: "{{ (value_json.worksheet.sheetData.row[20].c[2].v|float/1000)|round(3) }}"
        state_class: measurement
        unit_of_measurement: "€/kWh"
        json_attributes_path: "$.worksheet.sheetData.row[20].c[0]"
        json_attributes:
          - "v"
      - name: "GME 20-21"
        value_template: "{{ (value_json.worksheet.sheetData.row[21].c[2].v|float/1000)|round(3) }}"
        state_class: measurement
        unit_of_measurement: "€/kWh"
        json_attributes_path: "$.worksheet.sheetData.row[21].c[0]"
        json_attributes:
          - "v"
      - name: "GME 21-22"
        value_template: "{{ (value_json.worksheet.sheetData.row[22].c[2].v|float/1000)|round(3) }}"
        state_class: measurement
        unit_of_measurement: "€/kWh"
        json_attributes_path: "$.worksheet.sheetData.row[22].c[0]"
        json_attributes:
          - "v"
      - name: "GME 22-23"
        value_template: "{{ (value_json.worksheet.sheetData.row[23].c[2].v|float/1000)|round(3) }}"
        state_class: measurement
        unit_of_measurement: "€/kWh"
        json_attributes_path: "$.worksheet.sheetData.row[23].c[0]"
        json_attributes:
          - "v"
      - name: "GME 23-24"
        value_template: "{{ (value_json.worksheet.sheetData.row[24].c[2].v|float/1000)|round(3) }}"
        state_class: measurement
        unit_of_measurement: "€/kWh"
        json_attributes_path: "$.worksheet.sheetData.row[24].c[0]"
        json_attributes:
          - "v"

automation:
  #Aggiorna gli orari di massimo valore GME
  - id: gme_aggiornamento
    alias: GME Update
    description: ""
    trigger:
      - platform: time
        at: "00:00:00"
    condition: []
    action:
        - action: shell_command.gme
          data: {}
        - delay:
            seconds: 30
        - service: homeassistant.update_entity
          entity_id: sensor.gme_0_1
        - service: homeassistant.update_entity
          entity_id: sensor.gme_1_2
        - service: homeassistant.update_entity
          entity_id: sensor.gme_2_3
        - service: homeassistant.update_entity
          entity_id: sensor.gme_3_4
        - service: homeassistant.update_entity
          entity_id: sensor.gme_4_5
        - service: homeassistant.update_entity
          entity_id: sensor.gme_5_6
        - service: homeassistant.update_entity
          entity_id: sensor.gme_6_7
        - service: homeassistant.update_entity
          entity_id: sensor.gme_7_8
        - service: homeassistant.update_entity
          entity_id: sensor.gme_8_9
        - service: homeassistant.update_entity
          entity_id: sensor.gme_9_10
        - service: homeassistant.update_entity
          entity_id: sensor.gme_10_11
        - service: homeassistant.update_entity
          entity_id: sensor.gme_11_12
        - service: homeassistant.update_entity
          entity_id: sensor.gme_12_13
        - service: homeassistant.update_entity
          entity_id: sensor.gme_13_14
        - service: homeassistant.update_entity
          entity_id: sensor.gme_14_15
        - service: homeassistant.update_entity
          entity_id: sensor.gme_15_16
        - service: homeassistant.update_entity
          entity_id: sensor.gme_16_17
        - service: homeassistant.update_entity
          entity_id: sensor.gme_17_18
        - service: homeassistant.update_entity
          entity_id: sensor.gme_18_19
        - service: homeassistant.update_entity
          entity_id: sensor.gme_19_20
        - service: homeassistant.update_entity
          entity_id: sensor.gme_20_21
        - service: homeassistant.update_entity
          entity_id: sensor.gme_21_22
        - service: homeassistant.update_entity
          entity_id: sensor.gme_22_23
        - service: homeassistant.update_entity
          entity_id: sensor.gme_23_24

        - service: input_number.set_value
          data_template:
            entity_id: input_number.ora_picco_pun
            value: >
                {{ (state_attr('sensor.gme_max_mattino','max_entity_id').split('_')[1])|int }}
        - service: input_number.set_value
          data_template:
            entity_id: input_number.ora_picco_pun_sera
            value: >
                {{ (state_attr('sensor.gme_max_sera','max_entity_id').split('_')[1])|int }}
    mode: single

By(t)e

@andbad
Copy link

andbad commented Nov 4, 2024

@g1za nello script bash uso la variabile "DATE" come inizio e fine per i dati.
Ma come vedi dall'URL che richiamo sono valorizzabili a piacere:
https://www.mercatoelettrico.org/DesktopModules/GmeEsitiPrezziME/API/ExcelDownload/download?DataInizio=$DATE&DataFine=$DATE&Granularita=h&Mercato=MGP&Zona=CNOR&Tipologia=PrezziZonali&TutteZone=0

DATE è in formato AAAAMMGG e dopo le 13 ( mi pare) sono disponibili anche i dati del giorno dopo.

By(t)e

@virtualdj
Copy link
Owner

Se volete iniziare a testarla, ho pubblicato la v1.0.0 come pre-release qui. In HACS è sufficiente attivare la spunta Show beta versions per vederla comparire nell'elenco.

Non contiene ancora nessuna nuova funzionalità (a parte il download ad un minuto specifico anziché lo scoccare dell'ora), ma sarà la base di partenza per le prossime e soprattutto usa i dati dal nuovo sito GME.

Intanto la metto in funzione nel mio sistema HA di test per una settimana, per vedere se ci sono problemi, per poi renderla ufficiale per tutti.

@MicheleMercuri
Copy link

Perfetto, grazie, lo metto sul mio server pure io ;).

@g1za
Copy link
Contributor

g1za commented Nov 15, 2024

Anche io, con modalità debug abilitata; volevo mettere su un HA di test ma poi non avrei avuto la possibilità di verificarne bene il funzionamento :)

@virtualdj
Copy link
Owner

Nuova pre-release (mannaggia a me che non ho capito come usare i tag beta nelle versioni 🤦‍♂️) per correggere un errore che mi era sfuggito nel calcolo... dopo il primo giorno sbaglia la media perché non cancella i dati precedenti.

@g1za
Copy link
Contributor

g1za commented Nov 19, 2024

Non me ne ero accorto; a parte questo non ho notato cose strane. Mi sembra cambi le fasce correttamente.
Scarico.

@virtualdj
Copy link
Owner

Bene, questa mi pare a posto 🤞 quindi rilascio in maniera definitiva quella che sarà la "stabile" v1.0.1.

@virtualdj
Copy link
Owner

@g1za @MicheleMercuri
Ciao, ho pubblicato in pre-release la v2.0.0 che ha il sensore del prezzo zonale che volevate... A me sembra a posto, se potete datemi feedback.
Come spiegato nel README, negli attributi sono presenti i prezzi di oggi e domani che potete usare per i calcoli che dicevate di fare, mentre il valore del sensore cambia chiaramente di ora in ora (e si può legare al pannello energia di HA).

Spero sia di vostro gradimento (e, soprattutto, corretto)!

@g1za
Copy link
Contributor

g1za commented Dec 16, 2024

Ma grazie!
Scarico e faccio sapere.

@g1za
Copy link
Contributor

g1za commented Dec 16, 2024

@virtualdj un primo feedback che ti lascio è che sarebbe utile avere la stessa risoluzione del sensore PUN e zonale anche per i valori all’interno degli attributi, se possibile.

Ho verificato e (a parte gli arrotondamenti, vedi commento sopra) per ogni ora di oggi corrispondono sia PUN che prezzi zonali (testato su Nord). Poi cercherò di verificare il comportamento dopo le 15, per vedere come vengono caricati i valori di domani. Anche il valore del sensore ora corrente PUN e zonale corrisponde a quello del GME (con stessa risoluzione in questo caso).

Non ho pensato di salvarmi i prezzi delle fasce per confrontarli con quelli mostrati nella nuova versione ma immagino tu non abbia toccato questa parte di codice.

@g1za
Copy link
Contributor

g1za commented Dec 16, 2024

Come non detto, si vede che è solo una questione di arrotondamento dell'interfaccia; nel pannello sviluppatore i valori negli attributi hanno lo stesso arrotondamento usato nel sensore orario:

state_class: measurement
oggi_h_00: 0.11663
oggi_h_01: 0.11036
oggi_h_02: 0.1095
oggi_h_03: 0.11018
oggi_h_04: 0.10990000000000001
oggi_h_05: 0.11757
oggi_h_06: 0.135
oggi_h_07: 0.16865082
oggi_h_08: 0.17918
oggi_h_09: 0.15638999999999997
oggi_h_10: 0.12508
oggi_h_11: 0.11873
oggi_h_12: 0.1093
oggi_h_13: 0.10923999999999999
oggi_h_14: 0.12
oggi_h_15: 0.14627753999999998
oggi_h_16: 0.17918
oggi_h_17: 0.17918
oggi_h_18: 0.17443
oggi_h_19: 0.16953547
oggi_h_20: 0.14
oggi_h_21: 0.13072
oggi_h_22: 0.12483
oggi_h_23: 0.1175

@virtualdj
Copy link
Owner

sarebbe utile avere la stessa risoluzione del sensore PUN e zonale anche per i valori all’interno degli attributi, se possibile.

Sì, infatti, come ti sei accorto è solo un arrotondamento dell'interfaccia che non credo si possa modificare.

Ho verificato e (a parte gli arrotondamenti, vedi commento sopra) per ogni ora di oggi corrispondono sia PUN che prezzi zonali (testato su Nord)

Ottimo!

Poi cercherò di verificare il comportamento dopo le 15, per vedere come vengono caricati i valori di domani.

Teoricamente già ora dovresti avere quelli di domani già scaricati, perché quando cambi zona forza il download.

Anche il valore del sensore ora corrente PUN e zonale corrisponde a quello del GME (con stessa risoluzione in questo caso).

Bene!

Non ho pensato di salvarmi i prezzi delle fasce per confrontarli con quelli mostrati nella nuova versione ma immagino tu non abbia toccato questa parte di codice.

No, nessuna modifica in quella parte.

@g1za
Copy link
Contributor

g1za commented Dec 16, 2024

Teoricamente già ora dovresti avere quelli di domani già scaricati, perché quando cambi zona forza il download.

Quelli di domani (18 dicembre) non ci sono ancora, credo bisognerà aspettare dopo le 15 di oggi (17 dicembre).

Questi i valori del PUN:

state_class: measurement
oggi_h_00: 0.11663
oggi_h_01: 0.11036
oggi_h_02: 0.1095
oggi_h_03: 0.11018
oggi_h_04: 0.10990000000000001
oggi_h_05: 0.11757
oggi_h_06: 0.135
oggi_h_07: 0.16865082
oggi_h_08: 0.17918
oggi_h_09: 0.15638999999999997
oggi_h_10: 0.12508
oggi_h_11: 0.11873
oggi_h_12: 0.1093
oggi_h_13: 0.10923999999999999
oggi_h_14: 0.12
oggi_h_15: 0.14627753999999998
oggi_h_16: 0.17918
oggi_h_17: 0.17918
oggi_h_18: 0.17443
oggi_h_19: 0.16953547
oggi_h_20: 0.14
oggi_h_21: 0.13072
oggi_h_22: 0.12483
oggi_h_23: 0.1175
domani_h_00: null
domani_h_01: null
domani_h_02: null
domani_h_03: null
domani_h_04: null
domani_h_05: null
domani_h_06: null
domani_h_07: null
domani_h_08: null
domani_h_09: null
domani_h_10: null
domani_h_11: null
domani_h_12: null
domani_h_13: null
domani_h_14: null
domani_h_15: null
domani_h_16: null
domani_h_17: null
domani_h_18: null
domani_h_19: null
domani_h_20: null
domani_h_21: null
domani_h_22: null
domani_h_23: null
unit_of_measurement: €/kWh
icon: mdi:invoice-clock-outline
friendly_name: PUN orario

@g1za
Copy link
Contributor

g1za commented Dec 17, 2024

Ho verificato anche che i valori correnti di PUN e prezzo zonale si aggiornano correttamente allo scattare dell'ora, coerentemente con i valori orari negli attributi.

Al momento non mi vengono in mente ulteriori controlli da fare, a parte quello delle 15.

Ottimo lavoro. Grande!

@virtualdj
Copy link
Owner

Quelli di domani (18 dicembre) non ci sono ancora, credo bisognerà aspettare dopo le 15 di oggi (17 dicembre).

Sì ho sbagliato io credendo che il post fosse di "ieri" invece era già passata la mezzanotte 😁

@g1za
Copy link
Contributor

g1za commented Dec 17, 2024

Anche i dati di domani sono stati caricati e corrispondono al quelli sul sito GME.

@rayxxxxx
Copy link

Io personalmente utilizzo un addon (EMHASS) che in base a consumi previsti, costo di acquisto dell'energia, prezzo di vendita (prezzo zonale) e previsione di produzione fotovoltaica ottimizza la gestione energetica dell'abitazione permettendoti di comandare acquisto/vendita da/alla rete, carica/scarica batterie, accensione/spegnimento di carichi variabili. Il tutto per massimizzando una funzione di autoconsumo o profitto. Per questo add-on io utilizzo i prezzi zonali di oggi e di domani (appena resi disponibili, di solito fra le 14 e le 15, altrimenti continuo ad usare quelli di oggi), in quanto faccio fare l'elaborazione su 24h rolling.

@g1za so che non è il post più opportuno ma potresti darmi indicazioni per come produrre il csv dei prezzi e come fornirlo a EMHASS. Non ho mai provato EMHASS ma penso che combinato con l'ultima versione sui prezzi zonali di questa add-on possa essere molto utile.
Grazie

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants