Questa è la mia prima esperienza con le integrazioni di Home Assistant e, in generale, con Python. Purtroppo, mio malgrado, ho scoperto che la documentazione di Home Assistant per quanto riguarda la creazione di nuove integrazioni è scarsa e incompleta.
Nella prima versione (commit d239dae) ho provato ad effettuare un polling ogni 10 secondi sia per verificare se è sopraggiunto l'orario di aggiornamento dei prezzi che per calcolare la fascia oraria corrente. Ma, specie per il calcolo della fascia, non era il metodo corretto perché non è detto che l'aggiornamento avvenisse al secondo 0 della nuova fascia.
Così, cercando altri sorgenti in giro su GitHub, ho scoperto che esiste una funzione in Home Assistant chiamata async_track_point_in_time che consente di schedulare l'esecuzione di una routine in un determinato istante nel tempo, che viene rispettato perfettamente. La versione successiva è stata quindi riscritta utilizzando questo metodo (più efficiente).
Ovviamente non ho alcuna certezza che tutto questo sia la maniera giusta di procedere, ma funziona! Per chi di interesse, questi sono i progetti da cui ho tratto del codice interessante da utilizzare per il mio:
- zaubererty/homeassistant-mvpv
- Gradecak/spaarnelanden-containers
- nintendo_wishlist
- saso5/homeassistant-mojelektro
- YodaDaCoda/hass-solarman-modbus
- bruxy70/Garbage-Collection
- dcmeglio/alarmdecoder-hass
- BenPru/luxtronik e collse/Home-AssistantConfig per due esempi di come assegnare un entity-id predeterminato quando si usa anche l'unique_id senza ricevere errori
AttributeError: can't set attribute 'entity_id'(altra cosa non sufficientemente documentata di HomeAssistant) - dlashua/bolted, pippyn/Home-Assistant-Sensor-Afvalbeheer e questo articolo per come salvare e ripristinare lo stato di una entità con
RestoreEntity - Il componente di Home Assistant energyzero per il blocco del
config_flowgià configurato e per esprimere correttamente le unità di misura - La PR #99213 di Home Assistant per il suggerimento di usare
async_call_lateranziché sommare il timedelta all'ora corrente - La PR #76793 di Home Assistant per un esempio di come usare il cancellation token restituito da
async_track_point_in_time - I commit 1 e 2 per risolvere il warning nei log
[homeassistant.util.loop] Detected blocking call to import_module inside the event loop by custom integrationcomparso con la versione 2024.5.0 di Home Assistant e dovuto alle librerie importate - La configurazione del devcontainer con script ispirati dalla repository astrandb/viva e da post sulla community Home Assistant; utili anche questo e questo
- Questa parte di codice per effettuare il precaricamento corretto del modulo holidays con
async_add_import_executor_jobsenza che desse errori nel lint (si vede bene in questa commit)... Ma come si poteva capire? - La documentazione e questo esempio per capire come salvare un dato interno (il minuto di esecuzione, nello specifico) nella configurazione di Home Assistant, non mutabile, che richiede l'esecuzione di
async_update_entrysu una copia della stessa - Ho tentato di modificare i sensori per fare in modo che derivassero da
RestoreSensoranziché daRestoreEntity, come suggerito dalla documentazione ufficiale di Home Assistant, tuttavia ho dovuto desistere perché la funzioneself.async_get_last_sensor_data()può salvare solo 2 dati, cioènative_valueenative_unit_of_measurement(un esempio qui oppure qui). Questi però non sono sufficienti per il nostro scopo, perché serve anche sapere se il sensore è disponibile (self._available, che al limite si potrebbe rendere implicito connative_value = None) ma soprattutto il nome della fascia corrente (self._friendly_name) perPrezzoFasciaPUNSensorEntity. Quindi, in definitiva, ho lasciato tutto com'era, sfruttandoself.async_get_last_extra_data()e il dizionario personalizzato fornito dadef extra_restore_state_data(self)che comunque ripristinanative_valuee non lostatecome scrive la documentazione. - Grazie a ChatGPT ho scoperto che l'aggiunta di un
timedeltaa undatetime(pure timezone-aware) comunque "salta" le occorrenze della stessa ora locale (tipicamente le 2 di mattina) nella giornata di cambio ora. I calcoli vanno fatti sempre passando da UTC! - bramstroker/homeassistant-powercalc per capire come applicare la procedura descritta nella documentazione e fare in modo di non memorizzare gli attributi nel recorder che, nel caso di questa integrazione, sarebbero la lista dei prezzi zonali e del PUN orario.