Skip to content

Commit

Permalink
Risolto un bug fatale e aggiunti alcuni attributi
Browse files Browse the repository at this point in the history
- Risolto il fallito caricamento dell'integrazione di sabato con contratto tri-orario.
- Aggiunto attributo "Fascia successiva" al sensore "Prezzo zonale fascia corrente"
- Aggiunti attributi "Ora corrente", "Ora successiva", "Prezzo_successivo" e "Prezzo medio" al sensore "Prezzo zonale orario"
- Ora tutti i prezzi si arrotondano automaticamente all'ultima cifra decimale significativa.
  • Loading branch information
Gariam-1 authored Jan 4, 2025
1 parent ca256da commit 13ddfc2
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 22 deletions.
9 changes: 6 additions & 3 deletions custom_components/pzo_sensor/coordinator.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ async def _async_update_data(self):
"""Aggiornamento dati a intervalli prestabiliti."""

# Calcola l'intervallo di date per il mese corrente
date_end = dt_util.now().date()
date_end = dt_util.now().date() + timedelta(days=1)
date_start = date(date_end.year, date_end.month, 1) if self.month_average else date_end

# All'inizio del mese, aggiunge i valori del mese precedente
Expand Down Expand Up @@ -203,7 +203,7 @@ async def _async_update_data(self):
)

# Estrae i dati dall'archivio
self.pz_data.data = extract_xml(archive, self.pz_data.data, self.zone)
self.pz_data.data = extract_xml(archive, self.pz_data.data, self.zone, self.month_average)
archive.close()

# Per ogni fascia, calcola il valore dei prezzi zonali
Expand All @@ -213,7 +213,10 @@ async def _async_update_data(self):
self.pz_values.value[fascia] = pz_list[datetime.now().hour]
self.pz_values.value[Fascia.MONO] = mean(self.pz_data.data[fascia])
else:
self.pz_values.value[fascia] = mean(self.pz_data.data[fascia])
if len(self.pz_data.data[fascia]) > 0:
self.pz_values.value[fascia] = mean(self.pz_data.data[fascia])
else:
self.pz_values.value[fascia] = 0

# Calcola la fascia F23
self.pz_values.value[Fascia.F23] = self.pz_values.value[Fascia.F2] * 0.46 + self.pz_values.value[Fascia.F3] * 0.54
Expand Down
4 changes: 3 additions & 1 deletion custom_components/pzo_sensor/interfaces.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,19 @@ class Fascia(Enum):
F3 = "F3"
F23 = "F23"
ORARIA = "ORARIA"
ORARIA_NEXT = "ORARIA_NEXT"


class PricesData:
"""Classe che contiene i valori del prezzi orari per ciascuna fascia."""

def __init__(self):
self.data: dict[Fascia, list[float]] = {
Fascia.ORARIA: [],
Fascia.ORARIA: [0] * 24,
Fascia.F1: [],
Fascia.F2: [],
Fascia.F3: [],
Fascia.ORARIA_NEXT: [0] * 24
}


Expand Down
2 changes: 1 addition & 1 deletion custom_components/pzo_sensor/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,5 @@
"loggers": ["pzo_sensor"],
"requirements": [],
"single_config_entry": true,
"version": "1.0.0"
"version": "1.0.1"
}
37 changes: 27 additions & 10 deletions custom_components/pzo_sensor/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

from typing import Any
from zoneinfo import ZoneInfo
from datetime import datetime
from datetime import datetime, timedelta

from awesomeversion.awesomeversion import AwesomeVersion

Expand Down Expand Up @@ -215,7 +215,7 @@ def extra_state_attributes(self) -> dict[str, Any]:

# Nelle versioni precedenti di Home Assistant
# restituisce un valore arrotondato come attributo
return {ATTR_ROUNDED_DECIMALS: str(format(round(self.native_value, 3), ".3f"))}
return {ATTR_ROUNDED_DECIMALS: str(format(round(self.native_value, 6), ".6g"))}


class FasciaSensorEntity(CoordinatorEntity, SensorEntity):
Expand Down Expand Up @@ -271,9 +271,7 @@ def native_value(self) -> str | None:
def extra_state_attributes(self) -> dict[str, Any] | None:
"""Attributi aggiuntivi del sensore."""
return {
"fascia_successiva": self.coordinator.fascia_successiva.value
if self.coordinator.fascia_successiva
else None,
"fascia_successiva": self.coordinator.fascia_successiva.value if self.coordinator.fascia_successiva else None,
"inizio_fascia_successiva": self.coordinator.prossimo_cambio_fascia,
"termine_fascia_successiva": self.coordinator.termine_prossima_fascia,
}
Expand Down Expand Up @@ -384,15 +382,20 @@ def name(self) -> str:
@property
def extra_state_attributes(self) -> dict[str, Any]:
"""Restituisce gli attributi di stato."""

attributi = {
"fascia_successiva": str(format(self.coordinator.pz_values.value[self.coordinator.fascia_successiva], ".6g"))
}

if CommonSettings.has_suggested_display_precision:
return {}
return attributi

# Nelle versioni precedenti di Home Assistant
# restituisce un valore arrotondato come attributo
return {ATTR_ROUNDED_DECIMALS: str(format(round(self.native_value, 3), ".3f"))}
return {ATTR_ROUNDED_DECIMALS: str(format(round(self.native_value, 6), ".6g"))} | attributi

class PrezzoOrarioSensorEntity(CoordinatorEntity, SensorEntity, RestoreEntity):
"""Sensore che rappresenta il prezzo zonale della fascia corrente."""
"""Sensore che rappresenta il prezzo zonale orario."""

def __init__(self, coordinator: PricesDataUpdateCoordinator) -> None:
"""Inizializza il sensore."""
Expand Down Expand Up @@ -484,9 +487,23 @@ def name(self) -> str:
@property
def extra_state_attributes(self) -> dict[str, Any]:
"""Restituisce gli attributi di stato."""

data_corrente = datetime.now()
prossima_ora = data_corrente + timedelta(hours=1)
stesso_giorno = data_corrente.day == prossima_ora.day
stesso_mese = data_corrente.month == prossima_ora.month
attributi = {
"ora_corrente": data_corrente.hour,
"ora_successiva": prossima_ora.hour,
"prezzo_successivo": str(format(self.coordinator.pz_data.data[Fascia.ORARIA][prossima_ora.hour]
if (self.coordinator.month_average and stesso_mese) or stesso_giorno
else self.coordinator.pz_data.data[Fascia.ORARIA_NEXT][prossima_ora.hour], ".6g")),
"prezzo_medio": str(format(self.coordinator.pz_values.value[Fascia.MONO], ".6g"))
}

if CommonSettings.has_suggested_display_precision:
return {}
return attributi

# Nelle versioni precedenti di Home Assistant
# restituisce un valore arrotondato come attributo
return {ATTR_ROUNDED_DECIMALS: str(format(round(self.native_value, 3), ".3f"))}
return {ATTR_ROUNDED_DECIMALS: str(format(round(self.native_value, 6), ".6g"))} | attributi
20 changes: 13 additions & 7 deletions custom_components/pzo_sensor/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,13 +53,15 @@ def get_fascia(dataora: datetime, contract: int) -> tuple[Fascia, datetime]:
fascia = Fascia.F23
# Prossima fascia: alle 8 di un giorno non domenica, sabato o festività
prossima = get_next_date(dataora, 8, 1, True, True)

return fascia, prossima

elif dataora.weekday() != 5:
fascia = Fascia.F3
# Prossima fascia: alle 7 di un giorno non domenica o festività
prossima = get_next_date(dataora, 7, 1, True)

return fascia, prossima
return fascia, prossima

match dataora.weekday():
# Sabato
Expand Down Expand Up @@ -148,7 +150,7 @@ def get_next_date(dataora: datetime, ora: int, offset: int = 0, feriale: bool =
return prossima


def extract_xml(priceArchive: ZipFile, pz_data: dict, zone: str) -> list[dict[Fascia, list[float]]]:
def extract_xml(priceArchive: ZipFile, pz_data: dict, zone: str, mediaMese: True) -> list[dict[Fascia, list[float]]]:
"""Estrae i valori dei prezzi per ogni fascia da un archivio zip contenente un XML per giorno del mese.
Returns tuple(zonali, consumi zonali):
Expand All @@ -157,10 +159,11 @@ def extract_xml(priceArchive: ZipFile, pz_data: dict, zone: str) -> list[dict[Fa
"""
# Carica le festività
it_holidays = holidays.IT() # type: ignore[attr-defined]
oggi = datetime.now().date()

# Azzera i dati precedenti
for f in pz_data.keys():
pz_data[f].clear()
if (f not in [Fascia.ORARIA, Fascia.ORARIA_NEXT]): pz_data[f].clear()

# Esamina ogni file XML negli ZIP (ordinandoli prima)
priceFiles = priceArchive.namelist()
Expand Down Expand Up @@ -202,6 +205,7 @@ def extract_xml(priceArchive: ZipFile, pz_data: dict, zone: str) -> list[dict[Fa
int(dat_string.text[4:6]),
int(dat_string.text[6:8]),
)
domani = oggi < dat_date

# Verifica la festività
festivo = dat_date in it_holidays
Expand All @@ -219,12 +223,14 @@ def extract_xml(priceArchive: ZipFile, pz_data: dict, zone: str) -> list[dict[Fa
prezzo_string = prezzo_string.replace(".", "").replace(",", ".")
prezzo_pz = float(prezzo_string) / 1000

# Somma i valori dei diversi file per fascia per poter fare la media in seguito
if file_index > 0:
# Somma i prezzi orari dei diversi file per poter fare la media in seguito
if not domani or (mediaMese and oggi.month == dat_date.month):
pz_data[Fascia.ORARIA][ora] += prezzo_pz
else:
pz_data[Fascia.ORARIA].append(prezzo_pz)
pz_data[fascia].append(prezzo_pz)
pz_data[Fascia.ORARIA_NEXT][ora] = prezzo_pz

# Aggiunge il prezzo al calcolo delle varie fasce, eccetto quando è il primo giorno del mese successivo al giorno corrente
if oggi.month == dat_date.month: pz_data[fascia].append(prezzo_pz)

# Divide per il numero di file in cui erano presenti prezzi per completare la media
for ora in range(len(pz_data[Fascia.ORARIA])):
Expand Down

0 comments on commit 13ddfc2

Please sign in to comment.