Appearance
Guida: misure di consumo (Metering)
Obiettivo — Acquisire, monitorare e correggere le misure di consumo energetico dei POD, a partire dai flussi del SII (Sistema Informativo Integrato — Acquirente Unico).
Come entrano le misure
Le misure di un POD provengono dal SII in due modi, a seconda di come è configurato l'ambiente:
| Modalità | Chi la usa | Come |
|---|---|---|
| Automatica (WebDAV) | ambienti con accesso al SII | il sistema scarica ogni ora i file pubblicati dal distributore |
| Manuale (upload) | ambienti senza accesso diretto, o import | si caricano i file .xml/.zip (anche bulk) dal pannello |
In entrambi i casi i file confluiscono nello stesso punto e vengono elaborati allo stesso modo: misura → consumo per fascia (F1/F2/F3), pronto per consultazione e fatturazione.
Un file caricato più volte non genera duplicati: il sistema riconosce i file già visti, per nome e per contenuto, e li ignora.
Gli archivi caricati, e cosa c'era dentro
Nell'area Misure c'è l'elenco degli archivi con la dimensione, l'origine e lo stato. Clicca una riga e si apre il dettaglio di cosa conteneva:
| File XML | quanti ce n'erano dentro l'archivio |
| Letture estratte | quante misure ne sono uscite |
| POD distinti | quanti punti di prelievo toccava |
| Flussi SII | la ripartizione per tipo, con le barre |
| Nomi dei file interni | i primi quaranta, in ordine |
Esempio reale: un archivio da 2,58 GB conteneva 11.340 file XML e ha prodotto 760.636 letture su 126.294 POD.
L'intervallo delle misure può andare molto indietro rispetto al nome dell'archivio. Un
2026-09-11_2026-09-13.zipcon misure dal 31/12/2024 non è un errore: i flussi del SII contengono anche le rettifiche di mesi precedenti. È il motivo per cui caricando gli archivi di un mese si vedono riempirsi anche i mesi prima.
Lo stesso dato è in API:
bash
curl -s "${AUTH[@]}" "$API/v1/metering/file?limit=50"
curl -s "${AUTH[@]}" "$API/v1/metering/file/2026-09-11_2026-09-13.zip"Il contenuto non è conservato da nessuna parte. Nessuno tiene l'elenco dei file dentro uno zip da due gigabyte: si ricostruisce quando serve, dalle letture su Parquet, perché ogni lettura porta il nome dell'archivio da cui viene e quello dell'XML al suo interno. Costa qualche secondo e si paga solo all'apertura, invece di mantenere per sempre un registro che andrebbe tenuto allineato.
Il registro delle attività
Nell'area Misure di ogni tenant, sotto il caricamento, c'è il registro di tutto quello che è successo: caricamenti, letture, calcoli giornalieri e mensili, con l'esito di ciascuno. Le righe rosse sono le cose non riuscite.
Si filtra per fase e per origine:
| origine | cosa indica |
|---|---|
| a mano | file caricati dal pannello da una persona |
| dal SII | file scaricati automaticamente via WebDAV |
La distinzione conta: uno scarico automatico che non parte da giorni è un guasto, un caricamento manuale che non c'è è semplicemente una cosa che nessuno ha fatto. Prima erano indistinguibili.
Gli eventi registrati prima del 09/10/2026 non hanno l'origine: comparirà dai caricamenti successivi.
Tutto lo stato in una chiamata
bash
curl -s "${AUTH[@]}" "$API/v1/metering/panoramica"Restituisce in una risposta sola quello che altrimenti richiede tre chiamate — stato del sistema, cosa gira adesso, ultimi eventi — con una cache di 30 secondi. È pensata per chi integra le API, non per il pannello: quest'ultimo continua a usare le tre viste separate, perché si aggiornano a ritmi diversi e /attivita non deve svegliare il database.
Il campo da_cache dice se la risposta è quella memorizzata.
Il consumo giorno per giorno
bash
curl -s "${AUTH[@]}" \
"$API/v1/metering/pod/IT001E00000001/consumi?da=2026-08&a=2026-08&giorni=si"Il parametro giorni=si aggiunge il dettaglio giornaliero al consumo mensile: ogni giorno con F1/F2/F3, totale, quarti rilevati e se è completo.
La somma dei giorni può non fare il totale del mese, ed è corretto. Il mensile viene dai registri del contatore, che accumulano e coprono il periodo intero; il dettaglio giornaliero viene dalla curva, che ha solo i giorni arrivati. Se il mese è marcato
curva_incompletala differenza è esattamente quella — il dato fatturabile resta il mensile.
La curva a quarti d'ora
bash
curl -s "${AUTH[@]}" "$API/v1/metering/pod/IT001E00000001/curva?data=2026-08-28"Restituisce i 96 valori del giorno. Un 404 curva_non_trovata non è un guasto: vuol dire che per quel POD, in quel giorno, la curva non è arrivata. Il consumo del mese resta corretto, perché viene dai registri del contatore, che accumulano.
Se il 404 arriva su tutti i giorni di un tenant, il problema è un altro: la tabella del catalogo non è allineata. In quel caso lo dice
GET /v1/metering/statofra i problemi, areacatalogo— e si risolve riattivando il modulo per quel tenant.
Se ricevi un 503: il database si sta riaccendendo
Il database delle misure va in pausa quando nessuno lo usa, per non costare. La prima richiesta dopo la pausa lo riaccende, e ci mette qualche secondo. Se la riaccensione non finisce entro il tempo utile, la risposta è:
json
{ "error": { "type": "api_error", "code": "database_in_risveglio",
"message": "Il database era in pausa e si sta riaccendendo…" } }con HTTP 503 e l'intestazione Retry-After: 10.
Non è un guasto e non si è perso niente. La stessa identica richiesta, ripetuta dopo una decina di secondi, funziona. Chi integra queste API dovrebbe trattare questo 503 come un invito a riprovare, non come un errore da segnalare — è l'unico codice di errore del modulo che significa «richiamami fra poco».
I pannelli lo fanno già da soli: mostrano un avviso azzurro «il database si sta riaccendendo» e riprovano ogni otto secondi, invece di un errore rosso.
Il tetto d'attesa è di 20 secondi ed è tenuto sull'intera richiesta, non sulla singola interrogazione. La ragione è che API Gateway taglia a 29 secondi: superarli farebbe arrivare un 503 anonimo, senza codice né spiegazione. Il 27/09/2026 è successo — la pagina mostrava «Errore del server» mentre il database stava solo riaccendendosi.
Chiavi sviluppatore sulle misure
Dal 2026-10-06 tutte le rotte del modulo misure accettano anche le chiavi dmk_…, non solo le sessioni del pannello. Il tenant è legato alla chiave: l'header X-Tenant-Id viene ignorato, quindi una chiave non può leggere un altro tenant cambiando intestazione.
Lo scope decide cosa può fare:
| scope | può |
|---|---|
r | leggere: stato, POD, consumi, bollette, export |
rw | anche scrivere: rettifiche, caricamenti, rielaborazioni |
Una chiave r che prova a scrivere riceve 403 — il token è valido, l'operazione no.
L'attivazione e la disattivazione del modulo per un tenant non si raggiungono con una chiave API, qualunque sia lo scope: sono operazioni di provisioning della piattaforma.
Il fuso orario
Il sistema ragiona su Europe/Rome: «oggi», «il mese scorso» e gli orari delle corse notturne sono quelli italiani, ora legale compresa. Le schedulazioni a orario fisso girano su EventBridge Scheduler, che segue il cambio d'ora da solo.
Gli orari sono sempre in formato 24 ore: nei pannelli è imposto esplicitamente, perché la lingua italiana usa le 24 ore ma l'impostazione di sistema di chi guarda può forzare le 12 — e «3:05» senza AM/PM è ambiguo proprio di notte, che è quando girano le corse.
Gli istanti restituiti dalle API arrivano con il fuso scritto dentro, per esempio 2026-09-26T15:29:06+00:00. Non vanno interpretati: contengono gia' l'informazione. I pannelli li convertono nel fuso di chi guarda.
I dati restano conservati in UTC, che e' la scelta corretta per un archivio: la conversione avviene ai bordi, non nel magazzino. L'unica cosa che resta in UTC anche a vederla sono i timestamp nei log di CloudWatch, che li scrive AWS.
Se una lavorazione si interrompe
I file si elaborano a lotti, e ogni lotto viene registrato appena i suoi dati sono al sicuro. Se una lavorazione si interrompe — per un guasto, un archivio malformato, un riavvio — si perde solo il lotto in corso: tutto quello che è stato registrato prima resta, e la lavorazione successiva riprende da lì invece di ricominciare da capo.
Nel diario lo vedi così:
registro concluso Lotto 1 di 3 registrato: 2 file
registro concluso Lotto 2 di 3 registrato: 2 file
lettura fallito Elaborazione interrotta: …In questo caso i primi quattro file sono acquisiti e non verranno riletti. Non devi fare niente: il recupero automatico riprende entro un quarto d'ora dai file rimasti.
Rifare un lotto interrotto è sempre sicuro: le scritture riscrivono gli stessi valori, non sommano. È il motivo per cui il sistema preferisce rilavorare un lotto piuttosto che rischiare di dichiarare elaborato un file la cui lavorazione è morta a metà.
Quando vengono ricalcolati i dati
I tre livelli non si ricalcolano insieme, perché non costano lo stesso. Le cadenze sono due.
| Livello | Cos'è | Quando si ricalcola |
|---|---|---|
| Giornaliero | il consumo di ogni POD, giorno per giorno | ogni notte, e a ogni caricamento entro un quarto d'ora |
| Mensile | il totale del mese, quello che si fattura | insieme al giornaliero |
| Curva oraria | il profilo a quarti d'ora | domenica e mercoledì notte |
La separazione risponde a una misura. Su un tenant da 177.919 POD:
| Livello | Righe scritte | Tempo |
|---|---|---|
| Giornaliero | 27.685.896 | 37 minuti |
| Curva oraria | 178.047.392 | 37 ore |
Un fattore sessanta. Finché i due livelli erano un'unica corsa, una curva che non arrivava in fondo faceva scartare anche il giornaliero già calcolato: un archivio risulta letto solo a corsa conclusa, quindi l'interruzione annullava l'intero lavoro e non la sola parte mancante. Separati, il dato su cui si fattura è pronto ogni notte, indipendentemente dalla curva.
In pratica. I consumi giornalieri e mensili di un archivio caricato oggi sono disponibili entro un quarto d'ora. Il profilo a quarti d'ora degli stessi giorni compare alla prima corsa utile — domenica o mercoledì notte — e si può anticipare dalla pagina Misure, con Scrivi anche il profilo orario fra le azioni manuali.
La Sala Operativa
Risponde a una domanda sola: cosa sta succedendo adesso, senza dover mettere insieme la risposta da più pagine.
Tre fasce, dall'alto:
| fascia | cosa mostra |
|---|---|
| I cinque numeri | corse in esecuzione, file in coda, POD del mese, fatturabile, periodo giusto |
| In corso adesso · Diario | cosa gira in questo momento, accanto a ogni fase gia' conclusa o fallita |
| La catena · Automazioni | caricamento → lettura → archivio → aggregati, e cosa gira da solo |
Due cose da sapere per leggerla bene:
- I numeri sono del mese scelto in alto, non di tutto lo storico. È una distinzione che conta: su un tenant dove le rettifiche portano frammenti di decine di mesi vecchi, una percentuale complessiva non dice nulla sul mese che si sta per fatturare.
- Il riquadro «Da guardare» non è una lista di cose da fare. È l'elenco dei POD-mese che il sistema rifiuta di fatturare, con il motivo. Si svuota quando arrivano le letture che chiudono quei periodi, non con un intervento. E quei conteggi sono su tutti i mesi presenti.
Il diario si filtra per fase — caricamento, lettura, giornaliero, orario, mensile — ed è la stessa cosa che restituisce GET /v1/metering/eventi.
Il pannello POD
L'elenco dei POD di un mese, con il consumo gia' ripartito per fascia. Ogni riga apre il dettaglio e una bolletta in bozza impaginata secondo la delibera ARERA 181/06, che si salva in PDF dalla stampa del browser.
Il filtro predefinito è «Periodo giusto»: i POD la cui finestra di lettura coincide con il mese di calendario. Sono i candidati corretti per un confronto con una fattura vera — su quelli, se il numero non torna, il problema è nostro e si trova. È più ampio di «Quadrato», che pretende anche la conferma della curva.
La bolletta dichiara in testa di non essere un documento fiscale: contiene le quantità misurate, non corrispettivi né imposte. In fondo riporta la tracciabilità del calcolo — origine, esito del controllo, scarto dalla curva — che in una bolletta al cliente non comparirebbe.
Il pulsante Scarica PDF chiama GET /v1/metering/pod/{pod}/bolletta, che genera il documento lato server. L'anteprima accanto serve a guardarlo prima di scaricarlo, non a produrlo.
Il pannello Misure
Nel menu di Base9, la voce Misure apre una pagina che mostra l'intera catena, dal file del SII al consumo fatturabile. È il posto da cui partire quando qualcosa non torna: risponde nell'ordine a due domande, sta funzionando? e dove si è rotto?.
In alto c'è un giudizio complessivo — Tutto regolare, Da tenere d'occhio, Richiede intervento — e, se c'è qualcosa che non va, l'elenco dei problemi già ordinati per gravità, ciascuno con l'azione da fare. Sotto, le sei fasi in sequenza:
- Acquisizione dal SII — modalità, credenziali, quando è andato a buon fine l'ultimo scarico, file rimasti in coda;
- Archivio dei file grezzi — quanti file sono arrivati e quanti sono in errore;
- Trasformazione — quando ha girato l'ultima volta l'elaborazione notturna;
- Dati consolidati — POD, consumi giornalieri, curva oraria, letture d'indice, periodo coperto;
- Controllo di qualità — quanti mesi quadrano con il totale dichiarato dal distributore, e quanta energia sta nei mesi che non quadrano;
- Pronto per la fatturazione — conguagli aperti, e quanti riguardano periodi già fatturati.
Il numero delle fasi non è decorativo: la catena è una sequenza, e vedere che la fase 3 è ferma mentre la 2 procede dice subito dove guardare.
Un POD-mese non è un mese
I numeri della fase 4 e della fase 5 contano righe, non periodi di calendario. Un POD-mese è un POD in un mese: 9.641 POD su 35 mesi fanno 110.663 POD-mese. Allo stesso modo i consumi giornalieri sono POD × giorno × fascia, e la curva oraria è POD × giorno × ora. Leggerli come "mesi" o "giorni" porta a numeri impossibili.
Più in basso due schede permettono di scendere nel dettaglio: Mesi da verificare elenca, mese per mese, i POD con lo scarto maggiore fra il totale del distributore e quello calcolato dalla curva quartoraria; Conguagli elenca i periodi ricalcolati, con l'evidenza di quelli che erano già stati fatturati.
Tutto quello che il pannello mostra viene da una sola chiamata, GET /v1/metering/stato: se serve la stessa fotografia dentro un altro sistema, è quella da usare.
Configurazione (amministratore)
Dal pannello Misure c'è la sezione Configurazione dell'acquisizione, che fa tutto quello che segue senza scrivere una riga: modalità, P.IVA, indirizzo e credenziali del SII, conservazione, interruttore del modulo. Chi preferisce l'API trova qui sotto le stesse cose.
Chi amministra il tenant imposta la modalità e — se prevista — le credenziali WebDAV SII:
ingest_mode:manual(solo upload) ·webdav(solo automatico) ·both(misto);piva_venditore: identifica le cartelle del SII che contengono i vostri file;webdav_url: indirizzo del cloud SII (deve iniziare perhttps://);- credenziali SII (username + app-password): salvate in modo cifrato (mai visibili in chiaro, nemmeno rileggendo la configurazione);
hourly_hot_mesi: per quanti mesi la curva oraria resta su Aurora. È una finestra scorrevole per scelta, e il valore predefinito è 3. Non è un risparmio di spazio fine a se stesso: misurato su un tenant da 177.919 POD, la finestra a sei mesi vale 178 milioni di righe e 23 GB — l'82% dell'intero database — e la corsa che le scrive non rientra in nessun timeout ragionevole. La curva completa resta comunque nei Parquet, che sono l'archivio: alzare il valore la riporta su Aurora;curve_retention_mesi: per quanti mesi conservare le curve. Attenzione: oggi il valore si salva ma non è applicato — nessuna regola cancella le curve alla scadenza;enabled: interruttore del modulo. Afalsel'acquisizione automatica si ferma, ma i dati già raccolti restano consultabili e nulla viene cancellato.
Il PUT è un aggiornamento parziale
I campi che non invii restano come sono. In particolare, salvare per cambiare la P.IVA non cancella le credenziali SII già impostate: username e password si toccano solo inviandoli entrambi.
bash
# leggere la configurazione — le credenziali non vengono mai restituite
curl -s "${AUTH[@]}" "$API/v1/metering/config"json
{ "data": { "configurato": true, "ingest_mode": "both",
"piva_venditore": "01234567890",
"credenziali_impostate": true, "enabled": true,
"hourly_hot_mesi": 3, "curve_retention_mesi": 12,
"last_download_at": "2026-09-06T12:50:47" } }bash
# prima configurazione: modalità, indirizzo e credenziali (serve il ruolo admin del tenant)
curl -s -X PUT "${AUTH[@]}" -H "Content-Type: application/json" \
-d '{"ingest_mode":"both","piva_venditore":"01234567890",
"webdav_url":"https://siicloud.acquirenteunico.it/remote.php/dav/files/utente",
"sii_username":"utente.sii","sii_app_password":"la-app-password"}' \
"$API/v1/metering/config"json
{ "data": { "aggiornato": true, "ingest_mode": "both",
"webdav_url": "https://siicloud.acquirenteunico.it/remote.php/dav/files/utente",
"enabled": true, "credenziali_impostate": true } }bash
# cambiare solo la P.IVA: le credenziali restano quelle di prima
curl -s -X PUT "${AUTH[@]}" -H "Content-Type: application/json" \
-d '{"ingest_mode":"both","piva_venditore":"01234567890"}' \
"$API/v1/metering/config"bash
# sospendere l'acquisizione automatica senza perdere nulla
curl -s -X PUT "${AUTH[@]}" -H "Content-Type: application/json" \
-d '{"ingest_mode":"both","enabled":false}' \
"$API/v1/metering/config"Dopo aver cambiato le credenziali conviene verificarle subito, senza aspettare lo scarico notturno: dal pannello c'è il pulsante Scarica ora dal SII, via API è POST /v1/metering/fetch.
Se il tenant non ha il modulo attivo
Il modulo Misure non è una spunta: prepara un database dedicato per il tenant. Finché non è stato attivato quel database non esiste, e GET e PUT /v1/metering/config rispondono:
json
{ "error": { "type": "not_found_error", "code": "metering_non_attivo",
"message": "Il modulo metering non è attivo per questo tenant" } }con HTTP 404. Non è un guasto e non è un problema di permessi: è una domanda fatta su un tenant per cui non c'è ancora niente da configurare. Fino al 2026-10-14 la stessa situazione restituiva un 500 con dentro l'errore grezzo di PostgreSQL, che mandava a cercare un problema inesistente. Lo stesso 404 lo dà già GET /v1/metering/stato, ed è quello che nel pannello Misure fa comparire il riquadro di attivazione.
Se invece arriva un 503 database_in_risveglio, il modulo è attivo: è il database che era in pausa. Si riprova fra una decina di secondi — vedi Se ricevi un 503.
I flussi del SII e come vengono letti
Il Sistema Informativo Integrato consegna le misure in flussi diversi, identificati da un codice (CodFlusso) presente nel file e nel suo nome. Portano informazioni di tre nature diverse, e la natura determina l'uso che se ne fa in fatturazione.
Curva quartoraria
I 96 valori di una giornata, un quarto d'ora alla volta. È il livello di dettaglio più fine: permette di attribuire i consumi alle fasce F1, F2 e F3 secondo la delibera ARERA 181/06, e di ricostruire l'andamento orario di un punto di prelievo.
| codici | PDO2G PNO2G RFO2G RNO2G RNV2G VNO2G S2G SOS PDO PNO RFO RNO RNV VNO |
| dove | elemento <Ea>, con i 96 attributi E1…E96 e il giorno nel testo |
| uso | calcolo indipendente che verifica la cifra fatturabile |
Letture cumulative dei registri
Il valore progressivo del contatore per ciascuna fascia: cresce e non torna mai indietro. La differenza fra due letture è l'energia consumata nel periodo, ed è un dato che arriva dal distributore.
| codici | RT2G SM2G SMIS SNM SNM2G RSN RSN2G DS DS2G VP VP2G VPR2G AV AV2G AVR2G RT RTR2G SM e le varianti a registri dei flussi di curva |
| dove | <EaF1>…<EaF6> (attiva), <ErF1>…<ErF6> (reattiva), <PotF1>…<PotF6> (potenza) |
| data | DataMisura, DataRilevazione o DataPrest |
| uso | metodo delta registri, la seconda fonte della gerarchia |
Sostituzione del misuratore
Un flusso di sostituzione porta due letture con date diverse: l'ultima del contatore smontato (<Smontaggio>) e la prima di quello montato (<Montaggio>). Vengono conservate entrambe. Sono contatori distinti e il registro riparte da zero, quindi la differenza fra le due non è un consumo: il sistema riconosce l'azzeramento e non lo somma.
Consumo mensile dichiarato
Il consumo del mese già calcolato dal distributore, per fascia. Non è cumulativo: è la quantità consumata in quel mese. Si riconosce dal contenitore <Consumo> e dalla presenza di <MeseAnno>.
| codici | SNS |
| dove | <Consumo> con <EaF1>…<EaF3> |
| uso | totali dichiarati, la fonte più forte della gerarchia |
Flussi anagrafici
F2G, SNF e SOF descrivono le caratteristiche tecniche del punto — tensione, potenza impegnata, matricola del contatore, tariffa — e non contengono misure. Vengono riconosciuti e lasciati da parte senza generare segnalazioni.
Allo stesso modo, alcuni distributori consegnano insieme alle misure dei documenti di corrispettivi (voci di fatturazione del distributore): non sono flussi di misura e non entrano nella catena dei consumi.
Come si stabilisce la cifra da fatturare
La cifra che finisce in fattura deve essere un numero fornito dal distributore. Il calcolo dalla curva quartoraria serve a verificarla, non a sostituirla. L'ordine è:
- Totali dichiarati — il distributore comunica direttamente i totali del mese per fascia;
- Delta dei registri — differenza fra letture cumulative consecutive;
- Ricostruzione dalla curva — usata solo quando le prime due non sono disponibili.
Qualunque sia la fonte scelta, la riga porta anche il valore calcolato dalla curva e lo scarto fra i due. Se divergono oltre lo 0,2% il periodo esce come da_verificare e non va fatturato finché non è stato esaminato.
Flussi che non conosciamo ancora
Il SII e i distributori introducono nuovi codici nel tempo. Un file il cui codice non è fra quelli elencati non viene scartato: se contiene valori di misura, le sue letture vengono lette comunque. La classificazione serve a documentare e a scegliere il trattamento migliore, non a decidere se leggere.
I file che davvero non producono letture sono contati e dichiarati in GET /v1/metering/stato, così una consegna anomala si nota invece di passare inosservata.
Consultare i consumi
- Copertura (heatmap): per ogni POD, quali giorni del mese hanno misure e quali mancano — per individuare buchi e anomalie.
- Consumi mensili: per un POD, il consumo per fascia (F1/F2/F3) e totale, su un intervallo di mesi — è il dato che alimenta la fatturazione.
- Letture del giorno: il dettaglio di una singola giornata, con l'eventuale rettifica applicata.
- Curva quartoraria: i 96 valori di una giornata, per il drill-down puntuale su un POD.
Le fasce orarie (F1 giorno, F2 intermedia, F3 notte/festivi) seguono le regole ARERA e sono calcolate automaticamente, festività nazionali comprese.
Correggere una misura (rettifiche e immissioni)
Se una misura è errata o mancante, l'operatore può intervenire senza toccare il dato originale del SII:
- Rettifica: correggi il valore di una fascia in un giorno;
- Immissione: inserisci un valore mancante.
La correzione prevale sul dato SII e aggiorna subito il consumo, ma è reversibile: rimuovendola, torna automaticamente il dato originale del SII. Ogni intervento è tracciato (chi, quando, perché).
Il sistema applica la stessa logica anche in automatico: quando il distributore invia una rettifica di un giorno già ricevuto, questa prevale sulla misura originale, che però resta conservata e consultabile.
Usare le API
Tutte le chiamate richiedono due cose: il token e il tenant.
bash
API=https://api.base9.app
TOKEN="<il tuo id_token>" # vedi la guida Autenticazione
TENANT=TENANT_NAME
AUTH=(-H "Authorization: Bearer $TOKEN" -H "X-Tenant-Id: $TENANT")Vedere se il processo sta funzionando
Prima di guardare i numeri, conviene chiedere al sistema come sta. Una sola chiamata restituisce lo stato dell'intera catena — dallo scarico dal SII fino al dato fatturabile — con i problemi gia valutati:
bash
curl -s "${AUTH[@]}" "$API/v1/metering/stato"json
{
"data": {
"tenant": "TENANT_NAME",
"salute": "attenzione",
"ingest": {
"modalita": "both", "credenziali_impostate": true,
"ultimo_scarico": "2026-09-10T04:56:51", "ore_da_ultimo_scarico": 0.4,
"file_in_coda": 0
},
"trasformazione": { "ultima_elaborazione": "2026-09-10T02:09:32", "ore_da_ultima": 3.2 },
"aggregati": {
"pod": 9641, "righe_giornaliere": 7655970, "righe_orarie": 1198144,
"letture_indice": 455,
"pod_mese_consolidati": 110663, "mesi_calendario": 35,
"primo_giorno": "2023-11-29", "ultimo_giorno": "2026-09-09"
},
"qualita": {
"pod_mese_quadrati": 100364, "pod_mese_da_verificare": 10299, "percentuale_quadrati": 90.7,
"mwh_quadrati": 20366.0, "mwh_da_verificare": 1594.0,
"tipo_lettura": { "effettiva": 107352, "stimata": 2195, "mista": 1116 },
"giornate_parziali": 211
},
"fatturazione": { "conguagli_aperti": 0 },
"problemi": [
{ "gravita": "media", "area": "archivio", "messaggio": "1 file in stato di errore" },
{ "gravita": "bassa", "area": "qualita",
"messaggio": "211 giornate incomplete: il consumo di quei giorni e in difetto" }
]
}
}Come si legge. Il campo salute riassume tutto: ok se non c'e nulla da guardare, attenzione se ci sono solo anomalie minori, critica se c'e almeno un problema grave.
L'elenco problemi e la parte utile: non sono soglie decise da chi guarda la pagina, ma regole del sistema — uno scarico fermo da sei ore e un problema, da tre no. Ogni voce dice la gravita, l'area interessata e, quando esiste, cosa fare.
Le altre sezioni raccontano la catena in ordine: ingest (quando e arrivato l'ultimo file), trasformazione (quando e stata elaborata l'ultima misura), aggregati (quanto c'e), qualita (quanto e verificato) e fatturazione (cosa e pronto e cosa aspetta un conguaglio).
Chi amministra piu clienti puo interrogarli tutti dallo stesso punto, cambiando l'intestazione
X-Tenant-Id. Un utente normale vede solo il proprio.
Archivi letti solo in parte
archivio.file_troncati conta gli archivi che il job non è riuscito a leggere per intero. È diverso da un file illeggibile: lì manca il dato, qui il dato è su S3 e non è entrato. Finché non si rilegge, i consumi dei giorni coinvolti sono in difetto senza che i numeri lo dicano — ed è per questo che compare fra i problemi con gravità alta.
Nel pannello lo si vede in Sala Operativa → La catena → Lettura, riga «letti a metà».
Questi file restano in stato troncato e non processed: l'elaborazione li considera non ancora fatti e li riprende da sola alla corsa successiva, oppure subito con POST /v1/metering/reprocess.
Perché esisteva il problema
Fino al 2026-10-14 un archivio troncato restava processed, indistinguibile da uno letto per intero. La causa era un tetto di 5 GB sul totale decompresso di ogni oggetto: tarato come se quel totale stesse in memoria tutto insieme, mentre le voci si leggono una alla volta. Su 2026-10-01_10-03.zip — 3,38 GB compressi, 23,59 GB decompressi, rapporto 7:1 del tutto normale per XML — ci si fermava al 15% e restavano dentro 42.000 file, di cui 50.826 di competenza settembre. I guardiani ora misurano le tre cose che distinguono un archivio grosso e legittimo da uno malformato: la memoria viva sul cammino di discesa, la dimensione della singola voce e il rapporto di espansione (una zip bomb sta a 1.000.000:1, gli XML a 7:1).
Su quale periodo contano quei numeri
Senza parametri la chiamata conta su tutti i mesi presenti. È quasi sempre quello che serve per un pannello di sorveglianza — le rettifiche arrivano su periodi vecchi, e guardando un mese alla volta non si vedrebbero — ma non è quello che serve per chiudere un mese. Per quello c'è mese:
bash
curl -s "${AUTH[@]}" "$API/v1/metering/stato?mese=2026-09"La risposta dichiara sempre su cosa ha contato:
json
{ "data": { "periodo": { "mese": "2026-09", "etichetta": "2026-09" } } }Senza mese, oppure con mese=tutto, è { "mese": null, "etichetta": "tutto il periodo" }.
Quanto cambia, su dati reali:
| periodo | POD-mese | che quadrano | % |
|---|---|---|---|
| tutto il periodo | 1.038.801 | 360.001 | 34,7% |
mese=2026-09 | 161.694 | 25.214 | 15,6% |
mese=2026-07 | 174.579 | 48.255 | 27,6% |
Sono tutti numeri giusti, e rispondono a tre domande diverse. Leggere il primo come se fosse del mese che si sta chiudendo è lo scambio più facile da fare, ed è il motivo per cui periodo è nella risposta.
Cosa segue mese e cosa no. Seguono il periodo: qualita, fatturazione, aggregati.pod_mese_consolidati e le voci di problemi nelle aree qualita e fatturazione. Non lo seguono, perché sono lo stato di adesso e non appartengono a un mese di competenza: ingest, archivio, trasformazione, parco_pod e le voci di problemi nelle aree ingest, archivio, trasformazione, configurazione e catalogo.
Un mese di forma diversa da YYYY-MM (e diversa dalla parola tutto) viene rifiutato con 400 mese_non_valido: accettarlo e ignorarlo vorrebbe dire restituire il totale sotto l'etichetta di un mese.
Nel pannello
In Misure e in Sala Operativa il periodo si sceglie in alto a destra: la casella del mese, e accanto il pulsante tutto il periodo. I riquadri che dipendono dal periodo lo dicono nel proprio sottotitolo, perché il selettore sta in cima e i riquadri sono molto più in basso.
Verificare la copertura di un mese
Primo controllo da fare: quali POD hanno buchi. La risposta è paginata (50 POD per pagina), perché un tenant può averne migliaia.
bash
curl -s "${AUTH[@]}" "$API/v1/metering/heatmap?mese=2026-08&limit=50"json
{
"data": {
"object": "list",
"mese": "2026-08",
"pods": [
{ "pod": "IT001E00000012", "giorni_attesi": 31, "giorni_coperti": 31, "giorni_mancanti": [] },
{ "pod": "IT001E00000013", "giorni_attesi": 31, "giorni_coperti": 29, "giorni_mancanti": [4, 11] }
],
"has_more": true,
"next_cursor": "IT001E00000014"
}
}Per la pagina successiva si ripassa il cursore:
bash
curl -s "${AUTH[@]}" "$API/v1/metering/heatmap?mese=2026-08&starting_after=IT001E00000014"Leggere il consumo da fatturare
È il dato consolidato: consumo per fascia, mese per mese, con l'indicazione di dove viene il numero.
bash
curl -s "${AUTH[@]}" \
"$API/v1/metering/pod/IT001E00000011/consumi?da=2026-07&a=2026-07"json
{
"data": {
"pod": "IT001E00000011",
"periodi": [
{
"mese": "2026-07",
"kwh_f1": 5400.122, "kwh_f2": 3409.859, "kwh_f3": 4099.102,
"kwh_tot": 12909.083,
"origine": "delta_registri",
"stato": "quadrato",
"kwh_da_curva": 12909.086,
"scarto": 0.003,
"giorni_coperti": 31,
"lettura": {
"data_iniziale": "2026-06-30", "valore_iniziale": 308143.183,
"data_finale": "2026-07-31", "valore_finale": 321052.266
},
"tipo_lettura": "effettiva",
"giorni_stimati": 0,
"consumo_annuo": 69669.37,
"mesi_annuo": 8,
"fatturazione": { "stato": "da_fatturare", "versione": 1, "rif_fattura": null }
}
]
}
}Come si legge questa risposta. Il consumo fatturato è la differenza fra la lettura del 30 giugno (308.143,183) e quella del 31 luglio (321.052,266): 12.909,083 kWh. Sono le letture trasmesse dal distributore, non una nostra elaborazione — se il cliente contesta, la risposta è quella.
Il campo origine dice da dove viene la cifra:
| origine | significato |
|---|---|
totali_sii | i totali del mese per fascia dichiarati dal contatore |
delta_registri | differenza fra due letture cumulative del distributore |
curva | ricostruzione dai 96 quarti, usata solo dove mancano le altre |
curva_non_consolidata | mese non ancora elaborato, valore provvisorio |
Il campo stato è il controllo: quadrato significa che il nostro calcolo indipendente sulla curva conferma il dato del distributore (qui differiscono di 3 millesimi su 12.909 kWh). da_verificare significa che le due fonti divergono e quel mese non va fatturato senza controllare.
Per avere solo i mesi utilizzabili:
bash
curl -s "${AUTH[@]}" \
"$API/v1/metering/pod/IT001E00000011/consumi?da=2026-01&a=2026-07&solo_fatturabili=true"I campi richiesti dalla bolletta. tipo_lettura vale effettiva, stimata o mista, e giorni_stimati dice quanti giorni del mese sono stimati. È un'informazione che la bolletta deve dichiarare: un consumo stimato non può essere presentato come effettivo. Nel nostro archivio il 97,3% dei mesi è effettivo, il 2,7% è stimato o misto.
consumo_annuo è la somma dei 12 mesi che finiscono con quello fatturato, e mesi_annuo dice su quanti mesi è stato davvero calcolato: se è sotto 12 il dato è parziale, perché il POD non ha ancora un anno di storia.
Ricalcoli e conguagli
Quando una lettura effettiva arriva dopo che il periodo è già stato fatturato, il consumo cambia e serve un conguaglio — non una rifatturazione. Il sistema se ne accorge da solo: il periodo passa in stato da_conguagliare e finisce in una coda.
bash
# la coda dei conguagli da emettere
curl -s "${AUTH[@]}" "$API/v1/metering/conguagli?solo_fatturati=true"json
{
"data": {
"aperti": 1, "aperti_gia_fatturati": 1, "delta_kwh_totale": 99.878,
"conguagli": [
{ "id": 34, "pod": "IT001E00000011", "competenza": "2026-07", "versione": 2,
"kwh_precedente": 12909.083, "kwh_nuovo": 13008.961, "delta_kwh": 99.878,
"motivo": "rettifica del distributore",
"era_fatturato": true, "rif_fattura": "FT/2026/00987",
"stato": "aperto", "rilevato_at": "2026-09-08T09:30:21" }
]
}
}La voce dice tutto quello che serve per emettere la nota: quanto era stato fatturato, quanto è adesso, la differenza, il motivo e il riferimento della fattura originale. Una volta emessa:
bash
curl -s -X POST "${AUTH[@]}" -H "Content-Type: application/json" \
-d '{"rif_fattura":"FT/2026/01050-CONG"}' \
"$API/v1/metering/conguagli/34/chiudi"Il periodo torna in stato fatturato: la differenza è stata assorbita.
Il diario: cosa è successo, e perché
Le altre letture dicono com'è messo il sistema o cosa sta girando. Questa dice cosa è successo, in ordine di tempo, con una riga per ogni fase della catena.
bash
curl -s "${AUTH[@]}" "$API/v1/metering/eventi?limit=20"json
{ "data": { "eventi": [
{ "quando": "2026-09-24T19:02:11", "fase": "mensile", "esito": "concluso",
"messaggio": "284.335 POD-mese consolidati", "dettagli": { "righe": 284335 } },
{ "quando": "2026-09-24T18:44:02", "fase": "lettura", "esito": "saltato",
"messaggio": "Una lettura era già in corso su questo tenant: i file restano in attesa",
"dettagli": { "corsa_in_atto": "jr_3ef164cd…" } }
] } }Le fasi seguono la catena: caricamento, scompattamento, lettura, giornaliero, orario, mensile, registro. Con ?fase=lettura si guarda una sola fase.
I quattro esiti, e cosa significano davvero:
| esito | significato |
|---|---|
avviato | la fase è cominciata |
concluso | finita bene; i numeri sono in dettagli |
fallito | finita male; il motivo è nel messaggio |
saltato | non è partita, e il messaggio dice perché |
saltato è il più utile
Il caso tipico: carichi dei file mentre una lettura è già in corso sullo stesso tenant. Non si può avviarne una seconda — due letture elencano gli stessi file e scrivono il mensile ciascuna per conto suo, e il risultato finale diventa quello dell'ultima che finisce invece di quello con più dati.
I file restano in attesa, e il recupero automatico li riprende entro un quarto d'ora. Prima questa rinuncia avveniva in silenzio e i file aspettavano fino alla corsa notturna.
Sapere cosa sta succedendo adesso
Le altre letture dicono com'è andata. Questa dice cosa sta succedendo in questo momento, e serve a distinguere tre situazioni che dall'esterno si assomigliano ma richiedono decisioni opposte: una lavorazione in corso, una bloccata, una mai partita.
bash
curl -s "${AUTH[@]}" "$API/v1/metering/attivita"json
{
"data": {
"in_corso": [
{ "fase": "lettura", "stato": "RUNNING", "durata": "1 h 42 min",
"come": { "sorgente": "landing", "solo_nuovi": "si" } }
],
"quante_in_corso": 1,
"coda": { "file_non_ancora_letti": 2, "gb_non_ancora_letti": 4.67 },
"ultime_letture": [ … ]
}
}coda.file_non_ancora_letti conta i file presenti su S3 che non compaiono nel registro: o sono in lavorazione adesso, o aspettano la prossima corsa. È la misura di quanto lavoro resta.
Il campo come dice in che modalità sta girando: solo_nuovi: si legge solo i file nuovi, solo_nuovi: no rilegge tutto dai file originali, sorgente: curated rilegge i dati già estratti senza toccare i file di partenza.
Si può interrogare spesso
Legge solo Glue e S3, mai il database. Il pannello la rilegge ogni 10 secondi mentre qualcosa lavora e ogni 60 quando è fermo, senza costo apprezzabile.
Chiudere il mese: quante bollette si possono emettere
Il consumo di un mese dipende da due letture, non da trenta: la chiusura del mese precedente e quella del mese. Tutto il resto lo copre l'accumulo del contatore — un giorno mancante a metà mese non toglie nulla al totale, perché il delta del giorno dopo lo contiene già.
Questa è quindi l'unica domanda che conta prima di fatturare, e si risponde guardando i bordi della finestra invece del volume dei dati:
bash
curl -s "${AUTH[@]}" "$API/v1/metering/chiusura?mese=2026-03"json
{
"data": {
"mese": "2026-03",
"pod_mese_totali": 8836,
"fatturabili": 8211,
"non_fatturabili": 625,
"percentuale_fatturabile": 92.9,
"mwh_fatturabili": 1729.4,
"mwh_sospesi": 140.2,
"bordi": {
"su_pod_mese_da_registri": 8798,
"apertura_esatta": 8402, "chiusura_esatta": 8298,
"finestra_esatta": 8240, "percentuale_finestra_esatta": 93.3,
"mwh_finestra_esatta": 1741.8
},
"motivi_sospensione": {
"periodo_incompleto": 501, "periodo_esteso": 0,
"da_verificare": 124, "curva_incompleta": 0
},
"pronto": false
}
}pronto è vero solo quando non c'è nulla di sospeso. Finché è falso, motivi_sospensione dice cosa manca e GET /v1/metering/quadratura?stato=<motivo> dà l'elenco dei POD.
Scegliere i POD da confrontare con una fattura
bash
# i POD di luglio la cui finestra coincide col mese: i candidati giusti
curl -s "${AUTH[@]}" "$API/v1/metering/pod?mese=2026-07&stato=finestra_esatta&limit=20"
# un POD singolo, con le due letture che delimitano il periodo
curl -s "${AUTH[@]}" "$API/v1/metering/pod/IT001E00000001/consumi?da=2026-07&a=2026-07"Il filtro stato=finestra_esatta non è uno degli esiti salvati: è la domanda «questo mese è calcolato sul periodo giusto», e attraversa più stati. È il filtro corretto per un confronto con una bolletta vera, perché su quei POD una differenza è una differenza vera e non un disallineamento di periodo.
bash
# la bolletta in bozza, in PDF, di un mese
curl -s "${AUTH[@]}" -o bolletta.pdf \
"$API/v1/metering/pod/IT001E00000001/bolletta?mese=2026-07"
# piu' mesi: un PDF di piu' pagine, una per mese
curl -s "${AUTH[@]}" -o bollette.pdf \
"$API/v1/metering/pod/IT001E00000001/bolletta?da=2026-06&a=2026-08"Il PDF lo genera il server, non il browser: lo stesso documento per tutti, indipendente dalle impostazioni di stampa di chi lo scarica. Tre pagine per mese, con la struttura prevista da ARERA per la bolletta dell'energia elettrica:
| pagina | contenuto |
|---|---|
| 1 · Riepilogo del periodo | consumo fatturato, di cui stimato, consumo annuo, quota energia, dati della fornitura |
| 2 · Scontrino dell'Energia | quota consumi, quota fissa, quota potenza, accise e IVA, Box dell'offerta |
| 3 · Letture e Consumi | registri per fascia, potenza e reattiva, andamento giornaliero, storico |
Il listino: «Offerta Mixian»
Finché non esiste l'anagrafica delle offerte, la quota energia si calcola con un listino convenzionale:
Offerta Mixian · Monorario · 0,31 €/kWh su tutte le fasce (F1, F2, F3)Quello che non si inventa sono gli oneri di rete, la quota fissa, la quota potenza, le accise e l'IVA. Quelle voci compaiono nello Scontrino con la dicitura «da listino», vuote.
È una scelta, non una mancanza: un documento che stimasse gli oneri di sistema sarebbe più completo e meno vero, e su una bolletta la seconda cosa pesa più della prima. La struttura è quella definitiva — mancano i valori, e si vede quali.
Per la stessa ragione il documento non dichiara un emittente: l'intestazione del venditore — ragione sociale, indirizzo, partita IVA — arriverà dalla configurazione per tenant. Al suo posto c'è il marchio BASE9.
Le sezioni in dettaglio
| sezione | a cosa serve |
|---|---|
| Dati della fornitura | POD, periodo davvero misurato, giorni, tipo di lettura |
| Energia attiva da fatturare | il numero, con la media giornaliera accanto |
| Come si è arrivati a questo numero | le tre fonti possibili, con evidenziata quella usata |
| Ripartizione per fascia | F1/F2/F3 con le quote |
| Andamento giornaliero | barre impilate per fascia, una per giorno |
| Potenza ed energia reattiva | rapporto, cos φ, e la soglia ARERA del 50% |
| Consumo annuo | dichiarato, segnalando se proiettato su meno di dodici mesi |
| Storico | fino a tredici mesi a barre, col mese corrente evidenziato |
I due grafici non sono decorazione. Il totale dice quanto; l'andamento giornaliero dice come, e un giorno vuoto in mezzo al periodo o una fascia che sparisce si vedono lì e in nessun altro punto del documento — che sono esattamente le cose che fanno contestare una bolletta. Lo storico serve a capire in un colpo d'occhio se il mese è anomalo rispetto ai precedenti.
Il documento non riporta un'intestazione del venditore: arriverà da una configurazione per tenant, e finché non esiste preferiamo non dichiarare un emittente piuttosto che stampare un identificativo tecnico al posto di una ragione sociale. Se per il periodo richiesto non c'è nessun dato consolidato la risposta è 404 e non un PDF con i trattini al posto dei numeri — un documento vuoto verrebbe archiviato come se fosse una bolletta.
Gli stessi POD si sfogliano dal pannello POD, dove ogni riga apre il dettaglio, l'anteprima della bolletta e il pulsante per scaricarla.
Due numeri, non uno: fatturabili e finestra_esatta
Sono diversi apposta, e confonderli fa scartare un mese buono.
| campo | cosa chiede | quando è utile |
|---|---|---|
fatturabili | la finestra è giusta e la curva conferma il registro | per emettere le bollette senza guardare nient'altro |
bordi.finestra_esatta | la finestra è giusta | per sapere quanto del mese è calcolato sul periodo corretto |
finestra_esatta è sempre maggiore o uguale a fatturabili. La differenza sono i POD-mese dove il consumo è completo ma il confronto non si è potuto fare: la curva copre meno giorni del mese, e il delta dei registri no — il contatore accumula, quindi la differenza fra la lettura di apertura e quella di chiusura copre il periodo intero anche se in mezzo mancano dei giorni.
Misurato su un mese reale da 172.920 POD-mese: fatturabili 26,9%, finestra_esatta 63,7%. Lo scarto fra i due si spiega quasi per intero con i giorni che mancavano alla curva — su quelli a 29 giorni su 31, lo scarto mediano era del 6,6% contro il 6,5% di giorni assenti.
Guardare solo fatturabili avrebbe fatto sembrare inutilizzabile un mese che per quasi due terzi era calcolato sul periodo giusto.
Un mese si chiude, non scade. Non è fatturabile perché è finito, ma perché i bordi sono completi. Le letture di chiusura arrivano dal SII con qualche giorno di ritardo: per questo il sistema ricalcola da solo il mese precedente il 5 e il 12 di ogni mese. Calcolare un mese appena finisce garantisce di trovarlo con i bordi incompleti.
Vedere cosa non quadra prima di fatturare
Alla chiusura del mese, l'elenco dei POD da guardare:
bash
curl -s "${AUTH[@]}" "$API/v1/metering/quadratura?mese=2026-07"json
{
"data": {
"mese": "2026-07", "stato": "da_verificare",
"quadrati": 7557, "da_verificare": 534, "curva_incompleta": 2104,
"periodo_incompleto": 811, "totale": 11006,
"anomalie": [
{ "pod": "IT001E00000015", "kwh_fatturabile": 11919.603,
"kwh_da_curva": 397.989, "scarto": 11521.614,
"origine": "delta_registri", "giorni_coperti": 31,
"lettura_dal": "2026-06-30", "lettura_al": "2026-07-31" }
]
}
}Le anomalie sono ordinate per scarto decrescente: le prime sono quelle che pesano di più.
I tre esiti, e perché non sono la stessa cosa
Il consumo del mese viene calcolato in due modi indipendenti: il dato che dichiara il distributore, e la ricostruzione che il sistema fa sommando i quarti d'ora. Dal confronto nasce lo stato.
| stato | cosa significa | cosa farne |
|---|---|---|
quadrato | i due valori coincidono entro lo 0,2% | si fattura |
periodo_incompleto | la finestra fra le due letture è più corta del mese | non fatturare: consumo in difetto |
periodo_esteso | la finestra è più lunga: prende giorni del mese prima | non fatturare: consumo in eccesso |
da_verificare | coprono lo stesso periodo ma i numeri divergono | guardarlo prima di fatturare |
curva_incompleta | la curva copre meno del 90% del mese | il dato fatturabile resta valido |
solo_curva | nessun dato del distributore: solo la nostra ricostruzione dalla curva | non fatturabile per principio |
ka_non_verificata | contatore con costante di lettura su un totale dichiarato, senza riscontro che dica se applicarla | si dichiara, non si fattura |
periodo_chiuso | la finestra è più corta del mese ma coincide con un intervento dichiarato: stacco, riaggancio o cambio fornitore | nessun rimedio: il periodo è quello. evento_flusso ed evento_data dicono quale e quando |
fuori_scala | il consumo del mese si scosta oltre dieci volte, o scende sotto un decimo, rispetto alla storia dello stesso POD | guardarlo prima di fatturare: può essere vero, può essere un errore che le due fonti condividono |
registri_incoerenti | la serie degli indici del contatore ha un salto: un flusso porta un registro che non appartiene alla stessa serie | non fatturare: il valore mostrato viene dalla curva, e va guardato il flusso che ha rotto la serie |
Come si vede che un punto è stato staccato o riagganciato (dal 2026-10-18)
Dalle letture si legge in tre segnali insieme:
- Il flusso di prestazione —
DS/DS2Gper lo stacco o il cambio fornitore,AV/AV2Gper l'attivazione — che porta la data esatta dell'intervento. - La giornata troncata: l'intervento avviene a metà giornata, quindi quel giorno ha meno di 96 quarti d'ora. In un caso reale: 46 su 96.
- L'assenza, non lo zero. Un punto staccato sparisce dai flussi. Un punto fermo ma collegato continua a mandare 96 quarti a zero — sono due cose diverse e si distinguono.
Perché conta. Fino al 2026-10-18 questi POD finivano in periodo_incompleto, che significa «manca del dato, non fatturare». Per un punto staccato è falso: la finestra calcolata è giusta al giorno, e quei giorni sono il periodo intero. Misurato: circa 2.700 POD-mese a settembre hanno la finestra chiusa prima della fine del mese, e stacchi veri e buchi di dati erano indistinguibili.
Ora lo stato è periodo_chiuso e la riga porta evento_flusso ed evento_data.
Resta fuori dal fatturabile, di proposito: dire che il periodo è completo non decide da solo che si possa emettere una fattura per una frazione di mese. Quella è una scelta di prodotto, e si prende guardando questi POD — non per effetto collaterale di un cambio di stato.
Perché esiste fuori_scala (dal 2026-10-17)
Gli altri controlli confrontano fonti diverse dentro lo stesso mese: i registri del contatore contro la curva di carico. Funzionano finché l'errore colpisce una fonte sola.
Quando l'errore le colpisce entrambe, le due concordano e il controllo passa. È successo: un POD con costante di lettura 25 usciva a 925 kWh invece di 23.131, marcato quadrato, perché registri e curva erano sbagliati allo stesso modo.
fuori_scala confronta il mese con il passato dello stesso POD, che è un riferimento che l'errore non può corrompere perché è già stato scritto.
La banda è 0,1 – 10 volte. Misurata su 2.044.775 POD-mese reali: l'83,28% dei mesi sta fra metà e il doppio del consumo tipico del POD, e meno del 2% esce dalle dieci volte. I due errori trovati stavano a 0,04 e a 196 volte.
Il riferimento sono solo i mesi chiusi da settembre 2026 in poi: prima di allora il calcolo girava senza la costante Ka e senza il controllo sull'indice, e usare quei mesi significherebbe tarare il normale sull'anormale. Un mese ancora in corso non vale come metro.
Perché esiste registri_incoerenti (dal 2026-10-15)
Per un registro che accumula vale un'identità: la somma delle differenze giornaliere è la differenza fra l'ultimo e il primo indice. Il sistema calcolava entrambe da sempre e non le confrontava.
Quando non torna, la serie ha un salto. Il caso misurato: un POD il cui indice F1 va da 12,265 a 14,386 in tutto il mese riceve un flusso di rettifica con registro 12.022,024, un valore di un'altra serie. La finestra produce allora +12.008 salendo e −12.008 scendendo, e il filtro che scarta le differenze negative — scritto per ignorare le sostituzioni di contatore — tiene il salto in su e butta quello in giù. Un'oscillazione diventa un'accumulazione a senso unico: 207 kWh diventano 40.578.
Il verso conta. Se l'indice finale è più basso di quello iniziale il contatore è stato sostituito davvero: lì la somma delle differenze è la stima buona, e si accetta. Si rifiuta solo il caso pericoloso, la somma che supera l'escursione dell'indice: quella è energia inventata.
Misurato su settembre 2026: 551 POD-mese, 0,215 GWh — cioè quasi tutto lo scarto che restava rispetto al sistema in produzione.
Come è stato misurato, e perché gli stati sono cambiati il 2026-10-14
Gli stati sono stati verificati contro 14.748 fatture vere di luglio 2026 (confronto con il sistema in produzione). Il calcolo era corretto; l'assegnazione degli stati no.
| stato | POD | mediana vs fattura | entro ±5% |
|---|---|---|---|
quadrato | 4.977 | 1,000× | 97,1% |
da_verificare | 3.641 | 1,000× | 98,3% |
curva_incompleta | 1.236 | 1,000× | 98,1% |
periodo_esteso | 2.474 | 1,039× | 75,8% |
periodo_incompleto | 2.411 | 0,630× | 13,6% |
Prima della correzione la ricostruzione dalla curva usciva quadrato per costruzione: 847 POD-mese di giugno risultavano pronti da fatturare con 1-9 giorni di dato, e valevano lo 3,3% del consumo reale. Ora quel caso è curva_incompleta o solo_curva, e quadrato significa davvero emettibile.
Nota per chi legge i numeri: da_verificare e curva_incompleta sono accurati (1,000×). Non sono fatturabili per scelta — la cifra da fatturare deve venire dal distributore, non dal nostro calcolo di controllo — non perché siano sbagliati.
La costante di lettura del contatore (Ka)
I contatori con trasformatore di corrente registrano in unità secondarie: il valore del registro va moltiplicato per la costante Ka che il distributore dichiara nel flusso. Fino al 2026-10-14 non veniva applicata, e 388 POD risultavano consumare 109 MWh invece di 2.914 — venticinque volte sotto.
La convenzione è del POD, non del campo: dove i flussi portano i registri tutto è in unità secondarie, curva compresa; dove non ci sono registri i valori sono già finali. Quindi la costante si applica quando il calcolo passa dai registri (metodo delta_registri o totali_sii) e non quando viene dalla sola curva.
Misurato sulle fatture: con la costante applicata una volta la mediana è 1,00×; senza, 0,04×; applicandola due volte, 24,98×.
Perché periodo_incompleto è il più grave
Il distributore fattura dall'ultimo giorno del mese precedente all'ultimo giorno del mese. Se le nostre due letture dei registri non coprono quella finestra, il consumo che calcoliamo è in difetto esattamente dei giorni che mancano — e si fatturerebbe meno del dovuto.
Il controllo di quadratura non può accorgersene, ed è importante capire perché: la curva e il delta dei registri nascono dagli stessi flussi. Se manca il file di un giorno, lo perdono entrambi e continuano a coincidere perfettamente. Un controllo che confronta due fonti non rileva un'assenza che è in tutte e due. Per questo periodo_incompleto viene valutato prima degli altri, e l'avviso nel pannello è critico e non medio.
Le colonne lettura_dal e lettura_al nella risposta dicono qual è la finestra effettiva: confrontale con il mese e vedi subito quanti giorni mancano, e da che parte.
La distinzione fra gli ultimi due è quella che conta. Il delta dei registri copre il mese intero anche quando mancano dei giorni, perché il contatore accumula; la curva no, contiene solo i giorni arrivati. Se la curva è parziale le due cifre divergono per costruzione, e non c'è nulla da verificare: manca il termine di paragone, non è in dubbio il dato da fatturare.
Le due code si chiedono separatamente:
bash
curl -s "${AUTH[@]}" "$API/v1/metering/quadratura?mese=2026-07&stato=periodo_incompleto"I contatori nella risposta si riferiscono sempre all'intero mese: cambia solo l'elenco. giorni_coperti dice quanti giorni di curva ci sono in quel mese, ed è il numero da leggere per capire quanto è parziale.
Scendere al dettaglio di una giornata
Prima le tre fasce del giorno, con le eventuali rettifiche attive:
bash
curl -s "${AUTH[@]}" "$API/v1/metering/pod/IT001E00000012/letture?data=2026-08-11"Poi, se serve il massimo dettaglio, la curva quartoraria: i 96 valori della giornata.
bash
curl -s "${AUTH[@]}" "$API/v1/metering/pod/IT001E00000012/curva?data=2026-08-11"json
{
"data": {
"pod": "IT001E00000012",
"data": "2026-08-11",
"totale_kwh": 6.983,
"quarti": [0.073, 0.128, 0.121, 0.12, "…", 0.026, 0.027],
"tipo_flusso": "PDO2G",
"is_rettifica": false,
"fonte": "parquet"
}
}La curva risponde in qualche secondo, non in millisecondi: legge l'archivio storico, non la base dati calda. È pensata per il drill-down su un POD e un giorno, non per essere chiamata in ciclo su migliaia di POD. Per quello ci sono gli export.
Correggere una misura sbagliata
bash
curl -s -X POST "${AUTH[@]}" -H "Content-Type: application/json" \
-d '{"pod":"IT001E00000012","data":"2026-08-11","fascia":"F1",
"valore":92.0,"tipo":"rettifica","motivazione":"guasto contatore, valore da verbale"}' \
"$API/v1/metering/overrides"La risposta riporta il valore originale del SII, così resta tracciato cosa è stato sostituito. Per annullare la correzione e tornare al dato del distributore:
bash
curl -s -X DELETE "${AUTH[@]}" "$API/v1/metering/overrides/9001"Per vedere quali correzioni sono attive:
bash
curl -s "${AUTH[@]}" "$API/v1/metering/overrides?stato=attivo"json
{ "data": { "object": "list", "overrides": [
{ "id": 9001, "pod": "IT001E00000012", "data": "2026-08-11", "fascia": "F1",
"valore": 92.0, "tipo": "rettifica", "stato": "attivo",
"valore_sii_originale": 88.0, "operatore": "mario.rossi@example.com" } ] } }Estrarre i dati in CSV
Tre tagli, tutti con separatore ; e virgola decimale: si aprono in Excel senza conversioni.
bash
# tutti i POD di un mese — il taglio per la fatturazione
curl -s "${AUTH[@]}" -o mensile.csv "$API/v1/metering/export/mensile?mese=2026-08"
# un POD su piu mesi
curl -s "${AUTH[@]}" -o consumi.csv \
"$API/v1/metering/export/consumi?pod=IT001E00000011&da=2026-07&a=2026-08"
# dettaglio giorno per giorno e fascia per fascia
curl -s "${AUTH[@]}" -o letture.csv \
"$API/v1/metering/export/letture?pod=IT001E00000011&mese=2026-08"Il CSV porta il consumo e la sua provenienza, le stesse informazioni dell'API:
pod;mese;kwh_f1;kwh_f2;kwh_f3;kwh_tot;giorni_coperti;origine;stato;tipo_lettura;giorni_stimati;
kwh_da_curva;scarto;consumo_annuo;mesi_annuo;data_lettura_prec;data_lettura_fine;
lettura_prec;lettura_fine;stato_fatturazione;kvarh_tot;pot_max
IT001E00000011;2026-07;5400,122;3409,859;4099,102;12909,083;31;delta_registri;quadrato;
effettiva;0;12909,086;0,003;69669,370;8;2026-06-30;2026-07-31;308143,183;321052,266;
da_fatturare;412,880;18,240Per avere solo i mesi utilizzabili in fattura si aggiunge solo_fatturabili=true.
Estrazioni massive
Una risposta di questa API non puo superare i 6 MB. Oltre i 3 MB l'estrazione passa da sola a un collegamento temporaneo a un file su S3, e lo si puo chiedere esplicitamente con formato=link:
bash
curl -s "${AUTH[@]}" \
"$API/v1/metering/export/mensile?mese=2026-08&formato=link"json
{ "data": {
"url": "https://dev1-metering-curated-....s3.eu-south-1.amazonaws.com/export/...",
"righe": 652361, "byte": 32006796,
"troncato": false, "scade_tra_s": 3600, "generato_da": "aurora" } }Il collegamento dura un'ora. Si scarica come un file qualunque:
bash
curl -s -o letture.csv "<url restituito>"Per consumi e letture su tutti i POD si omette il parametro pod, e in quel caso formato=link e obbligatorio — l'estrazione sarebbe troppo grande per stare in una risposta:
bash
curl -s "${AUTH[@]}" \
"$API/v1/metering/export/letture?mese=2026-07&formato=link"Con formato=link il file lo scrive direttamente il database, per tutti e tre i tagli: il dato non passa dall'API, quindi non ci sono limiti di dimensione ne di tempo.
| Estrazione | Righe | Tempo |
|---|---|---|
| mensile di un mese | 8.091 | 1 s |
| consumi, tutto lo storico | 110.641 | 3 s |
| letture, tutti i POD di un mese | 652.361 | 6 s |
Il contenuto e identico a quello dell'estrazione inline: stesse colonne, stessa virgola decimale. Cambia solo come lo ricevi.
Se un'estrazione viene tagliata, lo dice. La risposta riporta
troncato: true, l'intestazioneX-Export-Troncatoe il file porta una riga finale di avviso. Un file incompleto che sembra completo e peggio di un errore.
Caricare file a mano
Dal pannello Misure c'è la sezione Carica misure a mano: si trascinano i file (o si scelgono), partono tutti insieme e l'elaborazione si avvia da sola quando l'ultimo ha finito di salire. Serve per i file scaricati dal portale del SII, o per rimediare a uno scarico automatico non riuscito.
Via API sono tre passaggi.
1. Chiedi gli indirizzi. I file di una stessa chiamata formano un lotto.
bash
curl -s -X POST "${AUTH[@]}" -H "Content-Type: application/json" \
-d '{"files":["09876543210_01234567890_202609_PDO2G_20260905231500_1DP2589.xml.zip",
"09876543210_01234567890_202609_S2G_20260905231500_1DP2589.xml.zip"]}' \
"$API/v1/metering/uploads"json
{ "data": {
"upload_id": "up_6075e226ae4b",
"file": [ { "nome": "09876543210_..._PDO2G_..._1DP2589.xml.zip",
"key": "landing/tenant=TENANT_NAME/source=manual/2026/09/up_6075e226ae4b/09876543210_...zip",
"url": "https://...s3...?X-Amz-Signature=..." } ],
"scartati": [ { "nome": "note.txt",
"motivo": "estensione non prevista (ammesse: .xml, .xml.zip, .zip)" } ],
"scade_tra_s": 900 } }2. Carica ogni file con una PUT sull'indirizzo ricevuto. I file non passano dall'API: vanno direttamente nell'archivio, ed è il motivo per cui non incontrano i limiti di dimensione del gateway.
bash
curl -s -X PUT --upload-file 09876543210_..._PDO2G_..._1DP2589.xml.zip "<url del file>"3. Fai elaborare il lotto, una volta sola, quando tutte le PUT sono finite:
bash
curl -s -X POST "${AUTH[@]}" "$API/v1/metering/uploads/up_6075e226ae4b/elabora"
# → 202 { "data": { "stato": "avviato", "run_id": "jr_daea...", "file_caricati": 2 } }Se non lo chiami non perdi nulla: i file verranno presi dall'elaborazione notturna.
Quando parte l'elaborazione
Dal pannello è automatica: parte da sola quando l'ultimo file del lotto ha finito di salire, e non serve aspettare nessun orario. Richiede qualche minuto — puoi lasciare la pagina, il lavoro prosegue. Via API la chiamata è tua: POST /v1/metering/uploads/{lotto}/elabora. Se non la fai, i file vengono presi dalla corsa notturna delle 02:00 UTC. Se qualcosa va storto arriva una mail: il fallimento del job è sorvegliato.
Una chiamata per lotto, non per file
elabora è separato dal caricamento apposta. Agganciarlo al singolo file farebbe partire un'elaborazione per ognuno: caricandone cinquanta, cinquanta elaborazioni sovrapposte.
Seguire l'avanzamento:
bash
curl -s "${AUTH[@]}" "$API/v1/metering/batches/up_6075e226ae4b"
# → { "data": { "batch_id": "up_6075e226ae4b", "stato": "in_elaborazione",
# "caricati": 2, "elaborati": 1, "errori": 0, "ignorati": 0 } }Gli stati sono nessun_file, in_coda, in_elaborazione, completato, completato_con_errori. caricati viene contato nell'archivio, gli altri sul registro dei file: serve a distinguere non ancora elaborato da mai caricato.
Nomi dei file. Non rinominare i file del SII: il nome porta distributore, venditore, competenza, tipo di flusso e istante di emissione, ed è da lì che vengono letti. L'identificativo del lotto viene messo nel percorso, proprio per lasciare il nome intatto. Un eventuale percorso nel nome (../, /etc/…) viene ridotto al solo nome finale: la scrittura non può uscire dallo spazio del tuo tenant.
Archivi grandi: non devi fare niente
Un archivio .zip può arrivare a 5 GB, e viene letto direttamente: non serve aprirlo prima. Il sistema se ne occupa:
- sopra i 100 MB il file sale a più parti da 64 MB. Ogni parte si ritenta da sola: se cade la rete non si ricomincia da capo, si riprende il pezzo;
- fino a 5 GB l'archivio viene letto così com'è dall'elaborazione, che lo apre in memoria e scende negli annidamenti da sola, distribuendo il lavoro su dieci macchine;
- poi gli aggregati, da soli.
Misurato su dati reali il 23 settembre 2026: un archivio da 1,46 GB contenente 1.206.368 letture su 111.949 POD è stato letto direttamente in 34 minuti, senza passaggi intermedi.
Due limiti diversi
Un archivio .zip arriva a 5 GB. Un file singolo — un XML sciolto — si ferma a 2 GB: viene letto tutto in memoria e oltre quella soglia non regge. Sopra i rispettivi limiti il caricamento rifiuta subito, invece di far scoprire il problema a lavoro finito.
Un archivio sopra i 5 GB va spezzato per contenuto in più .zip completi. Non con split né con zip -s: producono frammenti che non sono archivi validi e il sistema non può aprirli.
Lo scompattamento a monte esiste ancora, ma non serve più
Fino al 23 settembre 2026 gli archivi sopra i 2 GB venivano aperti da un passaggio dedicato, prima dell'elaborazione. Quel limite nasceva da un vincolo tecnico che non c'è più, e il passaggio costava caro: su un archivio con 25.598 voci dentro non aveva finito in tre ore, perché lavorava con una macchina sola invece di dieci. Ora si legge direttamente.
Oltre i 100 GB
Tecnicamente si può, ma il browser non è lo strumento giusto: la pagina deve restare aperta per ore. Meglio caricare con aws s3 cp (che fa il multipart da solo e riprende dopo un'interruzione) e poi far partire lo scompattamento dal pannello.
La finestra di validità degli indirizzi si adatta alla dimensione: 15 minuti per i file piccoli, fino a 6 ore per quelli grandi. I file singoli del SII sono comunque minuscoli — mediana 2,3 KB — quindi nell'uso normale non ci si pensa. Massimo 200 file per lotto.
Forzare uno scarico o una rielaborazione
Normalmente non serve: lo scarico dal SII gira da solo ogni ora. Questi due comandi servono quando non vuoi aspettare.
bash
# scarica subito dal SII (incrementale; se un giro è già in corso non viene duplicato)
curl -s -X POST "${AUTH[@]}" "$API/v1/metering/fetch"
# ricalcola gli aggregati di un periodo
curl -s -X POST "${AUTH[@]}" -H "Content-Type: application/json" \
-d '{"da":"2026-08","a":"2026-08"}' "$API/v1/metering/reprocess"Entrambi rispondono 202 e restituiscono un identificativo per seguire il lavoro. La rielaborazione riusa i dati già estratti.
Il profilo orario si chiede, e costa
Di difetto la rielaborazione scrive giornaliero e mensile, non l'orario. Per averlo serve "orario": true, ed è un parametro esplicito per una ragione misurata il 2026-10-16.
| come si scrive | ~1.800 parti da ~75 secondi l'una |
| quanto dura | oltre 30 ore per lotto |
| quanto costa | nell'ordine dei 150 USD |
| quanto occupa | 29 GB, il 66% dell'intera banca dati |
Per confronto, l'archivio analitico completo — che contiene i 96 valori al quarto d'ora per POD-giorno, quattro volte più fine — occupa 12,3 GB. La tabella oraria è più del doppio e porta meno informazione, e nessuna pagina la interroga: il drill-down della curva su un POD legge gli archivi analitici, non lei.
Quel giorno una corsa partita senza la distinzione ha scritto l'orario per otto ore filate, è andata in timeout senza concludere, e non ha registrato un solo file come elaborato — pronta a ripartire identica la notte dopo. Da allora il valore di difetto è daily in tutti e tre i punti che avviano una corsa, e nel CRM la casella porta scritto il prezzo accanto alla spunta.
da_grezzi svuota l'archivio e lo ricostruisce
"da_grezzi": true non è una modalità di lettura: è una ricostruzione da zero. Svuota l'archivio analitico del tenant e lo rifà leggendo tutti gli archivi grezzi su S3. Se la corsa non arriva in fondo — con decine di migliaia di file e un tetto di otto ore è già successo — l'archivio resta parziale.
Per questo richiede una conferma esplicita:
json
{ "da_grezzi": true, "confermo_svuotamento": true }Senza, la richiesta è rifiutata con 400 conferma_richiesta.
Serve solo quando cambiano le regole di lettura dei file. Se il problema è che alcuni archivi sono stati letti a metà, non serve: quelli restano in stato troncato, non contano come elaborati, e la prima rielaborazione normale li riprende da sola.
Controllo tipico di fine mese
Mettendo insieme i pezzi, la sequenza per chiudere un mese è questa:
bash
MESE=2026-08
# 1. ci sono buchi di copertura?
curl -s "${AUTH[@]}" "$API/v1/metering/heatmap?mese=$MESE" \
| python3 -c "import sys,json;d=json.load(sys.stdin)['data']
print([p['pod'] for p in d['pods'] if p['giorni_mancanti']])"
# 2. per un POD sospetto, dove manca?
curl -s "${AUTH[@]}" "$API/v1/metering/pod/IT001E00000013/letture?data=2026-08-04"
# 3. se il buco è noto e va colmato, si immette il valore
curl -s -X POST "${AUTH[@]}" -H "Content-Type: application/json" \
-d '{"pod":"IT001E00000013","data":"2026-08-04","fascia":"F1",
"valore":12.5,"tipo":"immissione","motivazione":"stima da verbale"}' \
"$API/v1/metering/overrides"
# 4. si estrae il mese chiuso
curl -s "${AUTH[@]}" -o chiusura-$MESE.csv "$API/v1/metering/export/mensile?mese=$MESE"Tutte le operazioni in una tabella
| Operazione | A cosa serve | Esempio sopra |
|---|---|---|
GET /v1/metering/stato | stato dell'intera pipeline e problemi rilevati | Vedere se funziona |
GET /v1/metering/heatmap | copertura POD × giorno di un mese | Verificare la copertura |
GET /v1/metering/pod/{pod}/consumi | consumo mensile fatturabile con provenienza | Leggere il consumo |
GET /v1/metering/eventi | Il diario del tenant: cosa è successo, fase per fase | Il diario |
GET /v1/metering/attivita | Cosa sta elaborando il sistema adesso | Sapere cosa succede |
GET /v1/metering/chiusura | Quante bollette si possono emettere per un mese | Chiudere il mese |
GET /v1/metering/quadratura | POD-mese che non superano il controllo; stato sceglie la coda | Vedere cosa non quadra |
GET /v1/metering/conguagli | periodi già fatturati e poi ricalcolati | Ricalcoli e conguagli |
POST /v1/metering/conguagli/{id}/chiudi | chiudere un conguaglio emesso | Ricalcoli e conguagli |
GET /v1/metering/pod/{pod}/letture | dettaglio di una giornata per fascia | Dettaglio giornata |
GET /v1/metering/pod/{pod}/curva | i 96 valori quartorari di un giorno | Dettaglio giornata |
POST /v1/metering/overrides | correggere o immettere una misura | Correggere una misura |
GET /v1/metering/overrides | elenco delle rettifiche attive | Correggere una misura |
DELETE /v1/metering/overrides/{id} | annullare una correzione | Correggere una misura |
GET /v1/metering/export/{tipo} | export CSV: mensile, consumi, letture | Estrarre i dati |
POST /v1/metering/uploads | ottenere l'indirizzo per caricare un file | Caricare file |
GET /v1/metering/batches/{id} | stato di un caricamento | Caricare file |
POST /v1/metering/fetch | forzare lo scarico dal SII | Forzare uno scarico |
POST /v1/metering/reprocess | ricalcolare un periodo | Forzare uno scarico |
GET /v1/metering/config | leggere la configurazione del tenant | Configurazione |
PUT /v1/metering/config | impostare modalità e credenziali SII | Configurazione |
Errori che puoi incontrare
| Codice | Significato | Cosa fare |
|---|---|---|
400 | parametro mancante o malformato (POD, data, mese) | le date sono YYYY-MM-DD, i mesi YYYY-MM |
404 | nessun dato per quel POD in quel giorno | verifica prima la copertura con la heatmap |
409 | scarico non previsto per il tenant | il tenant è in manual, oppure mancano le credenziali SII |
504 | la curva ha impiegato troppo | riprova: l'archivio storico risponde in secondi, non sempre uguali |
Aggancio con il resto di Base9
Il modulo Metering è agganciato solo tramite il POD (codice): il consumo di un POD si attribuisce al cliente/contratto giusto tramite le intestazioni storicizzate (chi era intestatario in quel periodo). Così la fatturazione usa il consumo corretto anche se il POD ha cambiato intestatario nel tempo.
Riferimento tecnico — API Reference, sezione Metering.
La documentazione e le specifiche leggibili da programma (
openapi.json,llms.txt) sono protette da credenziali di accesso: vanno richieste a chi amministra l'ambiente. Le API vere e proprie non sono toccate — usano il token come sempre.
Esportazione estesa (tracciato di consegna)
Dalla pagina POD del pannello, scegliendo il mese e premendo Esporta CSV, si ottiene un file con una riga per POD e una cinquantina di colonne, nominate come il tracciato di consegna usato dai sistemi di fatturazione.
Perché ci mette qualche minuto
Il file unisce due fonti, e non per disordine.
Le fasce F1/F2/F3 in kWh vengono dagli aggregati mensili: è il numero su cui si fattura, calcolato dalla curva quartoraria con il calendario ARERA. Registri, potenze e reattiva per fascia vengono invece dal dato grezzo archiviato, perché negli aggregati non esistono divisi per fascia.
Ricalcolare le fasce con una query diversa sarebbe più veloce e produrrebbe numeri che possono non coincidere con la bolletta. Si uniscono invece le due fonti, e l'unione di oltre centocinquantamila righe richiede qualche minuto.
I due numeri da guardare prima del file
Quando l'esportazione è pronta il pannello mostra quante righe contiene e, se ce ne sono, due avvisi:
- POD senza letture grezze nel mese. Hanno il dato fatturabile ma non hanno letture nel mese: il loro consumo arriva dai totali del SII. Per questi, registri e potenze per fascia restano vuoti — e sono parecchi, non è un caso raro.
- POD senza aggregato mensile. Il caso opposto: letture grezze presenti ma nessun calcolo mensile. Il totale viene preso dalle letture.
Il file contiene l'unione dei due insiemi: nessun POD viene lasciato fuori. La colonna delivery_notes dice riga per riga in quale dei due casi ci si trova, insieme al metodo di calcolo e alla copertura in giorni.
Cosa non c'è, e perché
Il tracciato di riferimento prevede anche lo switch, i registri di potenza e la reattiva divisa fra entro e oltre soglia. Quelle colonne non ci sono, invece di esserci vuote:
- lo switch non è un dato che il sistema riceve;
- un registro di potenza non esiste: la potenza è una punta nel periodo, non un contatore che avanza;
- la soglia della reattiva non è implementata da nessuna parte nel sistema, e un numero calcolato qui con una regola scelta a tavolino sarebbe un numero che nessuno ha verificato.
Una colonna assente si nota. Una colonna piena di un valore sbagliato no.
Il periodo di consegna
delivery_from e delivery_to sono le date di lettura, non il primo e l'ultimo giorno del mese: è il periodo a cui il consumo si riferisce davvero. Quando le date di lettura mancano si ricade sui confini del mese.
L'intervallo in cui esistono letture grezze è un'altra cosa, e sta in prima_lettura_grezza e ultima_lettura_grezza.
Il collegamento di scarico
Quando l'esportazione è pronta compare il pulsante Scarica, e il collegamento che usa è lo stesso che l'API restituisce nel campo url.
È un collegamento firmato: si apre direttamente, senza token, e scade dopo dodici ore — la data esatta è nel campo scade_il. Dopo la scadenza il file resta dov'è ma il collegamento non vale più: basta rifare l'esportazione, che si può ripetere quante volte si vuole.
Chi usa le API lo trova così:
GET /v1/metering/export/tracciato?mese=2026-07
→ { "job": "671823d9360f4c5b", "stato": "in_coda" }
GET /v1/metering/export/tracciato?job=671823d9360f4c5b
→ { "stato": "pronto", "file": "consumi-TENANT_NAME-2026-07.csv",
"url": "https://…?X-Amz-…", "righe": 173499,
"senza_letture": 167221, "scade_il": "2026-10-13T02:40:27Z" }Le fasi che si vedono mentre lavora sono, in ordine: risveglio — il database con capacità minima zero si mette in pausa e va svegliato — poi athena, aurora, unione, fatto.
Se dice «fallito», aspetta ancora un momento
Un primo tentativo può cadere sul risveglio del database. Le elaborazioni vengono ritentate automaticamente, e il secondo tentativo di solito riesce: il pannello lo sa e continua a controllare per qualche minuto prima di mostrare un errore. Se usi le API direttamente, fai lo stesso.
Un avvertimento su luglio 2026
Per luglio il sistema ha i consumi di 173.438 POD ma le letture grezze di 6.278: quel mese è stato caricato dai totali mensili del SII, non dai flussi giornalieri. Nell'esportazione estesa le fasce ci sono tutte, ma registri, potenze e reattiva per fascia sono vuoti per il 96 % delle righe — e il file lo dichiara, riga per riga, in delivery_notes.
Da agosto in poi i flussi giornalieri ci sono, e le colonne tecniche si riempiono.

