# OCPP

> Riferimento del driver OCPP - il sistema centrale integrato, i certificati dei punti di ricarica, i tag dei connettori e la regola di denominazione Meter, Status e Transaction.

Il driver OCPP fa di Ganter Lab il **sistema centrale** per i punti di ricarica di
veicoli elettrici che parlano Open Charge Point Protocol. Come per LoRaWAN, la
direzione è rovesciata: la stazione non si collega al caricatore, è il **punto di
ricarica a collegarsi a Ganter Lab** su un WebSocket, a registrarsi e a spingere
dentro la propria telemetria.

Il sistema centrale integrato parte quando il primo dispositivo OCPP abilitato viene
caricato nel connector in funzione, e si ferma quando l'ultimo viene rimosso o
disabilitato: senza alcun punto di ricarica configurato, sulla porta non ascolta
proprio nulla. Aggiungerne uno lo fa tornare, senza riavviare l'applicazione. Ogni
dispositivo che configuri rappresenta **un punto di ricarica**, identificato dall'id
con cui si collega.

## Preparare il punto di ricarica {#prepare-the-charge-point}

È il punto di ricarica a chiamare questa stazione e, di fabbrica, non sa dove si
trovi. La pagina di ogni dispositivo OCPP porta la scheda **Preparare il punto di
ricarica**, con quello che va inserito nelle impostazioni OCPP del punto di ricarica,
scritto per questa stazione:

| Che cosa configurare sul punto di ricarica | Che cosa dà la scheda |
|---|---|
| Indirizzo del sistema centrale | `wss://<indirizzo>:19521/<id-del-punto-di-ricarica>`, prima con l'indirizzo dato dal nome di questa stazione (il « Nome di rete » della configurazione del server OPC UA integrato, o il nome del computer finché è vuoto), poi una volta per ogni indirizzo IPv4 che questa stazione ha su una rete, ciascuno con un pulsante di copia. Un punto di ricarica che verifica il nome del server ha bisogno dell'indirizzo dato dal nome; uno che non lo verifica accetta uno qualsiasi, e allora basta quello della sua rete. |
| Identità del punto di ricarica | L'**Identificativo** del dispositivo oppure, finché è vuoto, il nome che la stazione dà al dispositivo. Molti punti di ricarica aggiungono da sé la propria identità all'indirizzo: su questi, inserire l'indirizzo solo fino alla porta, e l'identità nel suo campo. |
| Sicurezza | TLS con certificato client, quello che OCPP chiama profilo di sicurezza 3. I profili 1 e 2, che non hanno certificato client, non sono accettati. Il certificato del punto di ricarica riporta la sua identità nel nome comune o in un nome alternativo DNS (vedere [Certificati](#certificates)). |
| Certificato radice del sistema centrale | Il percorso completo di `GanterLabConnector-<station>.pem`, il certificato radice di questa stazione, che il punto di ricarica installa per fidarsi del sistema centrale, con il pulsante **Apri la cartella**, che mostra il file in Esplora file di Windows. Il pulsante funziona nella finestra della stazione stessa; in un browser su un altro dispositivo resta in grigio e dice perché. |

La scheda è aperta finché il punto di ricarica non si è collegato dall'apertura della
stazione, e si richiude una volta collegato: resta nella pagina per la prossima volta
che il punto di ricarica verrà configurato. Un punto di ricarica il cui certificato
non è garantito da nessuna radice installata in Windows viene rifiutato alla prima
connessione e attende in [Accesso delle apparecchiature](#equipment-access).

Il file viene scritto al primo avvio del sistema centrale, appena un punto di ricarica è
registrato, e fino ad allora la scheda lo dice. È lo stesso file per tutti i punti di
ricarica di questa stazione, e non cambia quando cambiano il nome o gli indirizzi della
stazione (vedere [Il certificato radice della stazione](#the-stations-root-certificate)).

**Ogni punto di ricarica che ha ricevuto un file da una versione precedente ha bisogno di
questo, installato una volta.** Al primo avvio di questa versione, una stazione i cui punti
di ricarica possono avere un file precedente mostra sulla scheda un avviso, **Il file di
questa stazione è cambiato**, solo in quell'esecuzione. L'avviso è un promemoria, non
l'istruzione: installare il nuovo file una volta su ogni punto di ricarica di una stazione
che aveva già punti di ricarica, che la scheda mostri l'avviso o no. Da allora un punto di
ricarica che verifica il nome del server accetta la stazione.

## Sistema centrale e porte {#central-system-and-ports}

| Che cosa | Valore |
|---|---|
| Versioni di protocollo | OCPP **1.6**, **2.0**, **2.0.1** e **2.1** (negoziazione del sottoprotocollo WebSocket; JSON) |
| Ascolto | Tutte le interfacce, porta TCP **19521**, solo TLS |
| Indirizzo del punto di ricarica | `wss://<station-address>:19521/<charge-point-id>` |
| Identità | L'ultima parte del percorso WebSocket è l'id del punto di ricarica |

L'ascolto è sempre in TLS; un ascolto in HTTP semplice viene rifiutato ovunque tranne
che in loopback, che esiste solo per le prove interne al processo. Un punto di ricarica
si registra con la sua BootNotification (a cui si risponde con un intervallo di
heartbeat di 60 secondi), e ogni badge presentato per l'autorizzazione viene accettato:
Ganter Lab osserva la ricarica, non gestisce tariffe né accessi.

## Certificati {#certificates}

Il lato server dell'handshake TLS presenta un certificato firmato dalla radice propria di
questa stazione (vedere [Il certificato radice della stazione](#the-stations-root-certificate)).
Ogni punto di ricarica deve presentare un **certificato client**:

1. Deve essere attendibile in uno di due modi: costruisce una catena valida su questa
   macchina Windows, fino a una radice installata lì, senza errori di politica TLS;
   oppure proprio questo certificato è stato approvato in **Accesso delle apparecchiature**
   sulla pagina di questo driver (più sotto). In entrambi i casi deve essere entro le sue
   date di validità. Un controllo fallito rifiuta la connessione e il diario registra quale
   controllo è fallito.
2. Il suo common name di soggetto oppure un nome alternativo di soggetto DNS deve
   **nominare l'id del punto di ricarica** con cui si collega. Un certificato che nomina
   un punto di ricarica diverso da quello del percorso di connessione viene rifiutato,
   anche se approvato.

Un handshake senza certificato client viene lasciato cadere prima che passi alcun dato.

### Il certificato radice della stazione {#the-stations-root-certificate}

| Che cosa | Valore |
|---|---|
| La radice | Creata una volta per profilo, al primo avvio del sistema centrale o del server di rete LoRaWAN. Il suo soggetto è `Ganter Lab Connector (<station>)`, dove `<station>` è il nome di rete in quel giorno. Non scade mai e non viene mai sostituita da sola: rinominare il computer, cambiare il nome di rete o cambiare gli indirizzi della stazione la lascia com'è. |
| Il file | `GanterLabConnector-<station>.pem`, solo la parte pubblica, nella cartella dati sotto `ua\pki\station`. È lo stesso file per un punto di ricarica e per un gateway LoRaWAN, che lo installa come `tc.trust`. |
| Il certificato che presenta il sistema centrale | Firmato da quella radice. Riporta il nome di rete della stazione (il « Nome di rete » della configurazione del server OPC UA integrato; il nome del computer finché è vuoto), `localhost` e ogni indirizzo IPv4 della stazione, perciò un punto di ricarica che verifica il nome del server (profilo di sicurezza 3) lo accetta. Quando cambia il nome di rete o un indirizzo, viene emesso di nuovo, da solo, soltanto questo certificato, senza nulla da fare sul punto di ricarica. |
| Il certificato del server OPC UA | Non usato qui. Il server OPC UA integrato tiene il proprio certificato per i client OPC UA. |

Una radice memorizzata che non si può più aprire, per esempio perché è stata scritta da un
altro account Windows, viene sostituita da una nuova. Ogni punto di ricarica ha allora
bisogno del nuovo file, una volta, e la scheda lo dice.

### Accesso delle apparecchiature {#equipment-access}

Un punto di ricarica il cui certificato non è garantito da nessuna radice installata in
Windows, perché è autofirmato o emesso dall'autorità del produttore stesso, non ha bisogno
che quella radice sia installata su questo computer. La sua prima connessione viene
rifiutata, e il suo certificato attende in **Accesso delle apparecchiature**, in fondo alla
pagina del driver OCPP, la stessa scheda della pagina del driver OPC UA, fino a una
decisione:

| Gruppo | Che cosa elenca | Che cosa si può fare |
|---|---|---|
| In attesa di approvazione | Ogni certificato rifiutato, sotto l'id del punto di ricarica con cui si è collegato: la sua impronta SHA-256, l'ultimo tentativo e quanti tentativi, e i suoi dettagli (soggetto, emittente, nomi di dominio, date di validità). | **Approva** ammette il certificato dalla prossima connessione del punto di ricarica. **Blocca** continua a rifiutarlo senza elencarlo di nuovo qui. **Scarta tutti i certificati in attesa** svuota l'elenco senza approvare né bloccare nulla. |
| Apparecchiature approvate | I certificati approvati o importati, con chi ha deciso e quando. | **Ritira l'approvazione** chiude la connessione del punto di ricarica e riporta il suo certificato nell'elenco. **Importa certificato** approva il certificato pubblico di un punto di ricarica prima della sua prima connessione. |
| Apparecchiature bloccate | I certificati bloccati. Un certificato bloccato viene rifiutato anche se Windows lo considera attendibile. | **Sblocca** riporta il certificato nell'elenco, senza approvarlo. |

Ogni certificato viene approvato a sé, mai l'autorità che lo ha firmato: un secondo punto
di ricarica dello stesso produttore attende quindi la propria approvazione. Confrontare
l'impronta con quella indicata dal punto di ricarica prima di approvarlo. L'approvazione non
cambia quale punto di ricarica sia il certificato: resta ammesso solo sotto l'id del punto di
ricarica che nomina, e solo entro le sue date di validità. Un certificato che Windows
considera già attendibile viene ammesso come prima e non compare mai qui; nulla viene
approvato automaticamente.

Le decisioni sono conservate nella cartella dei dati della stazione, in `ua\pki\ocpp`, e
sopravvivono a un riavvio. I comandi vengono disegnati solo per un ruolo che può configurare
il Connector, e agiscono solo nella finestra della stazione stessa: un browser su un altro
dispositivo legge la scheda senza modificarla, e nessuno strumento di un agente approva un
certificato. L'elenco tiene fino a 100 certificati in attesa di approvazione; quando è
pieno, uno nuovo resta rifiutato ma non viene elencato, e la scheda lo dice.

## Campi di connessione {#connection-fields}

| Campo | Che cos'è | Formato | Predefinito |
|---|---|---|---|
| Identificativo | L'**id del punto di ricarica** che questo dispositivo rappresenta: lo stesso id che il caricatore mette alla fine del suo URL di connessione e che porta nel proprio certificato. | Testo libero, confrontato senza distinguere maiuscole e minuscole. Vuoto ricade sul nome ripulito del dispositivo. | vuoto |

Non ci sono campi per host, porta o credenziali: è il caricatore a tenere i dettagli
della connessione, e a questa stazione serve solo sapere quale punto di ricarica il
dispositivo intende. Non ci sono nemmeno campi per l'intervallo di interrogazione. OCPP
funziona a spinta, cioè è il punto di ricarica a inviare i messaggi MeterValues e
StatusNotification secondo la propria cadenza, e i tag si aggiornano dagli ultimi dati
ricevuti su un ciclo fisso di un secondo.

Un punto di ricarica che non si è ancora collegato, o un connettore che non ha ancora
riferito nulla, non ha quindi **alcuna lettura**, non una lettura fallita. I suoi tag
restano vuoti e nel diario non viene registrato alcun fallimento: un valore che il punto di
ricarica non ha ancora inviato è il protocollo che funziona.

### Lo stato di salute del punto di ricarica {#the-charge-points-health}

Poiché un punto di ricarica invia i suoi valori quando li ha, il silenzio dei suoi tag non
può distinguere uno che non ha ancora riferito da uno che non c'è più. Il suo stato di
salute, il punto sulla sua riga nell'albero e la colonna **Stato di salute** nella pagina
del driver, segue invece il suo collegamento al sistema centrale di questa stazione:

| Situazione | Stato di salute |
|---|---|
| Configurato, e non collegato da quando la stazione è stata aperta | **Non connesso** |
| Collegato, non ha ancora inviato nulla | **Connesso** |
| Collegato e in invio | **Connesso**, oppure **Parzialmente connesso** quando alcuni dei valori che ha inviato non si leggono |
| Caduto: fermato, staccato o isolato dalla rete | **Non connesso**, finché non si ricollega |
| Il sistema centrale non in ascolto | **Non connesso** |
| Disabilitato | **Disabilitato** |

Finché il punto di ricarica è collegato, un connettore che non ha ancora riferito nulla non
conta contro di lui. Per al massimo dieci secondi dopo che una modifica al punto di ricarica
viene salvata, o che il Connector si avvia, si legge **Non ancora noto**: rimettere al suo
posto il dispositivo può riavviare il sistema centrale, e il punto di ricarica impiega un
momento a ricollegarsi.

## Tag {#tags}

Un tag OCPP legge un **connettore** del punto di ricarica (connettore nel senso di
OCPP: una posizione di presa, numerata da 1). In OCPP 2.0, 2.0.1 e 2.1 il numero è quello dell'**EVSE**, perché lì
i connettori ripartono da 1 dentro ogni EVSE. Esistono tre generi di tag, distinti dal
**suffisso del nome del tag**, che viene convalidato:

| Il nome del tag finisce in | Che cosa legge | Tipo sensato |
|---|---|---|
| `Meter` | L'ultimo valore campionato di contatore che il connettore ha riferito (MeterValues di OCPP; in OCPP 2.x anche i valori che un TransactionEvent porta durante una ricarica). L'unità è quella che il caricatore invia, di solito Wh. Il server conserva gli ultimi 10 campioni e il tag legge il più recente. Un connettore che non ha mai riferito nulla si legge come valore vuoto, non come zero. | Float oppure Double |
| `Status` | Il testo di stato del connettore dall'ultima StatusNotification (per esempio `Available`, `Faulted`). In OCPP 2.x un EVSE con più di un connettore si legge come il più significativo fra loro: `Faulted` prevale su `Occupied`, `Occupied` su `Reserved`, `Reserved` su `Available`, e `Available` su `Unavailable`. Un EVSE che non ha ancora riferito uno stato si legge come valore vuoto. | String |
| `Transaction` | Il numero della transazione in corso sul connettore, quello che chiedono i comandi RemoteStopTransaction e GetTransactionStatus: in OCPP 1.6 il numero che questa stazione ha dato alla transazione al suo avvio, in OCPP 2.x l'identificativo proprio della stazione di ricarica, esattamente come l'ha inviato. Viene riempito quando una transazione comincia e svuotato quando finisce, quindi senza transazioni in corso si legge come testo vuoto. Finché nessuna transazione comincia o finisce dopo che il punto di ricarica si è collegato, si legge come valore vuoto, perché una transazione potrebbe essere già in corso. | String |

Un nome senza nessuno di questi suffissi viene rifiutato dalla convalida: chiama i tag
come `Connector1Meter`, `Connector1Status` e `Connector1Transaction`.

| Campo | Che cosa fa | Valori | Predefinito |
|---|---|---|---|
| Connettore di ricarica | Il numero che questo tag legge: quello del connettore in OCPP 1.6, quello dell'EVSE in OCPP 2.x. | 1 o più | 1 |
| Tipo di dato | Il tipo OPC UA con cui il valore viene esposto. | Int32, Float, Double, String | Float |

I tag OCPP sono **di sola lettura**: il campo dell'accesso non offre alcuna scelta
scrivibile, e una scrittura viene rifiutata invece che simulata. Comandare un punto di
ricarica è un comando a sé, descritto qui sotto, non un valore scritto su un tag.

## Comandi {#commands}

Un punto di ricarica si comanda oltre che leggere. Ogni dispositivo OCPP porta i
comandi qui sotto come **metodi sul dispositivo** nello spazio degli indirizzi OPC UA
proprio di questa stazione, così un client OPC UA connesso a questa stazione
emette un comando chiamando il metodo.

Ogni comando prende l'**id del punto di ricarica** come primo argomento e restituisce
come risultato la risposta propria del punto di ricarica.

| Comando | Altri argomenti | Che cosa fa |
|---|---|---|
| ChangeAvailability | ConnectorId, Type (`Operative` oppure `Inoperative`) | Mette o toglie di servizio un connettore. |
| ChangeConfiguration | Key, Value | Imposta una chiave di configurazione sul punto di ricarica (OCPP 1.6). |
| ClearCache | nessuno | Svuota la cache di autorizzazione del punto di ricarica. |
| GetConfiguration | Key | Legge una chiave di configurazione (OCPP 1.6). |
| RemoteStartTransaction | IdTag | Avvia una sessione di ricarica per un gettone. |
| RemoteStopTransaction | TransactionId | Ferma una sessione in corso. |
| GetTransactionStatus | TransactionId | Chiede se una transazione è ancora in corso (OCPP 2.x). |
| Reset | nessuno | Riavvia il punto di ricarica. |
| UnlockConnector | ConnectorId | Rilascia il cavo da un connettore. |
| SetChargingProfile | ConnectorId, Limit, NumberOfPhases | Imposta un limite di potenza di ricarica, in watt. ConnectorId 0 limita l'intero punto di ricarica; un altro numero imposta il limite predefinito delle sessioni che quel connettore ricarica. |
| SetVariables | ComponentName, VariableName, AttributeType, AttributeValue | Imposta una variabile di un componente (OCPP 2.x). |
| GetVariables | ComponentName, VariableName, AttributeType | Legge una variabile di un componente (OCPP 2.x). |

`AttributeType` è uno tra `Actual`, `Target`, `MinSet`, `MaxSet`.

**Da dove viene il TransactionId.** RemoteStopTransaction e GetTransactionStatus agiscono su una transazione, indicata dal suo numero. Leggilo nel tag `Transaction` del connettore su cui la sessione ricarica (l'EVSE in OCPP 2.x), per esempio `Connector1Transaction`, e passalo così come si legge. Un testo vuoto lì significa che su quel connettore non è in corso nessuna transazione.

**Un catalogo per ogni versione.** I comandi mantengono i nomi qui sopra qualunque versione parli
il punto di ricarica, e la stazione invia ciascuno nella forma che quella versione definisce. In
OCPP 2.0, 2.0.1 e 2.1 i connettori sono raggruppati sotto degli EVSE, e il numero passato come
ConnectorId indica l'EVSE.

| Comando | In OCPP 1.6 | In OCPP 2.0, 2.0.1 e 2.1 |
|---|---|---|
| ChangeAvailability | Agisce sul connettore indicato; 0 è l'intero punto di ricarica. | Agisce sull'EVSE indicato; 0 è l'intera stazione di ricarica. |
| RemoteStartTransaction | Invia l'IdTag, e il punto di ricarica sceglie il connettore. | Parte come RequestStartTransaction, con l'IdTag come gettone centrale e un proprio identificativo di avvio; la stazione di ricarica sceglie l'EVSE. |
| RemoteStopTransaction | Il TransactionId è il numero che questa stazione ha dato alla sessione al suo avvio. | Parte come RequestStopTransaction; il TransactionId è l'identificativo proprio della stazione di ricarica, passato così com'è come testo. |
| Reset | Un riavvio completo. | Un riavvio immediato. |
| UnlockConnector | Rilascia il connettore indicato. | Rilascia il primo connettore dell'EVSE indicato. |
| SetChargingProfile | 0 imposta il profilo massimo del punto di ricarica; un altro connettore riceve un profilo predefinito. | 0 imposta il profilo massimo della stazione di ricarica; un altro EVSE riceve un profilo predefinito. |
| ChangeConfiguration, GetConfiguration | Come nella tabella qui sopra. | Non fanno parte di queste versioni: la stazione di ricarica risponde con un errore, e il comando fallisce. |
| GetTransactionStatus, SetVariables, GetVariables | Non fanno parte di questa versione: il punto di ricarica risponde con un errore, e il comando fallisce. | Come nella tabella qui sopra. |

**Aspettare la risposta.** Un comando non è finito quando la stazione lo ha inviato. La
stazione tiene aperta la chiamata finché il punto di ricarica non risponde proprio
all'ordine che ha inviato, riconosciuto dall'identificatore di correlazione che viaggia
con esso, e solo allora riferisce che è riuscito e restituisce la risposta. Tre cose lo
chiudono altrimenti, ciascuna riferita come fallimento con il suo motivo:

- Il punto di ricarica non è collegato, oppure la sua connessione non è aperta. Non
  viene inviato nulla.
- Il punto di ricarica risponde con un errore OCPP, per esempio per un comando che non
  implementa. Il codice di errore è il motivo.
- Passano **30 secondi** senza alcuna risposta. Un comando a cui nessuno ha risposto è
  un fallimento, mai un successo.

Un comando emesso per un punto di ricarica che nessun dispositivo porta, oppure che non
è collegato, viene rifiutato subito invece di essere messo in coda.

## Rilevamento {#discovery}

**Rileva** sul driver OCPP elenca i punti di ricarica **attualmente collegati** al
sistema centrale, e leggere i canali di un candidato propone un tag `Meter`, un tag
`Status` e un tag `Transaction` per ogni connettore che il punto di ricarica ha riferito finora.

Il **primo punto di ricarica si configura sempre a mano**. Nulla si può collegare
prima che il sistema centrale ascolti, e lui ascolta solo quando qui esiste un
dispositivo OCPP, quindi una scansione di un'installazione senza alcun punto di ricarica
configurato non trova nulla e lo dice. Aggiungi quel primo dispositivo con l'id con cui
il caricatore si collegherà; dopo di che, un caricatore che si è collegato si può
rilevare. Il flusso generale del rilevamento è descritto nella pagina
[Connector](connector).

L'id viene confrontato **senza distinguere maiuscole e minuscole**, nel certificato,
nel percorso di connessione e rispetto al dispositivo: un caricatore che si collega
come `cp-a` con un certificato che nomina `CP-A` è lo stesso punto di ricarica di un
dispositivo il cui Identificativo si legge `CP-A`.

Un punto di ricarica che c'è già rilegge i suoi connettori dalla sua stessa pagina: **Rileva tag**, nell'intestazione della sua scheda **Tag**, offre i tag `Meter`, `Status` e `Transaction` di ogni connettore che ha riferito mentre era collegato e per cui il dispositivo non ha ancora un tag (vedere [Rilevare i tag di un dispositivo](connector-discovery#discovering-a-devices-tags)).
