# OCPP

> Referência do driver OCPP: o sistema central embutido, certificados de ponto de recarga, tags de conector e a regra de nomeação Meter, Status e Transaction.

O driver OCPP faz do Ganter Lab o **sistema central** de pontos de recarga de veículos
elétricos que falam o Open Charge Point Protocol. Como no LoRaWAN, o sentido é
invertido: a estação não conecta ao carregador, o **ponto de recarga conecta
ao Ganter Lab** por um WebSocket, se registra e empurra a telemetria dele para cá.

O sistema central embutido inicia quando o primeiro dispositivo OCPP habilitado é carregado
no connector em execução, e para quando o último é removido ou desabilitado: sem
nenhum ponto de recarga configurado, nada escuta na porta. Adicionar um o traz de
volta, sem reiniciar a aplicação. Cada dispositivo que você configura representa **um
ponto de recarga**, identificado pelo id sob o qual ele conecta.

## Preparar o ponto de recarga {#prepare-the-charge-point}

O ponto de recarga é quem disca para esta estação e, de fábrica, não sabe onde ela
está. A página de cada dispositivo OCPP traz o cartão **Preparar o ponto de recarga**
com o que informar nas configurações OCPP do ponto de recarga, escrito para esta
estação:

| O que configurar no ponto de recarga | O que o cartão dá |
|---|---|
| Endereço do sistema central | `wss://<endereço>:19521/<id-do-ponto-de-recarga>`, primeiro com o endereço pelo nome desta estação (o "Nome de rede" da configuração do servidor OPC UA embutido, ou o nome do computador enquanto ele está vazio), depois uma vez para cada endereço IPv4 que esta estação tem numa rede, cada um com botão de copiar. Um ponto de recarga que confere o nome do servidor precisa do endereço pelo nome; um que não confere aceita qualquer um deles, e então o da rede dele basta. |
| Identidade do ponto de recarga | O **Identificador** do dispositivo, ou, enquanto ele está vazio, o nome que a estação dá ao dispositivo. Muitos pontos de recarga acrescentam a identidade ao endereço sozinhos: nesses, informe o endereço só até a porta, e a identidade no campo próprio dela. |
| Segurança | TLS com certificado de cliente, o que o OCPP chama de perfil de segurança 3. Os perfis 1 e 2, que não têm certificado de cliente, não são aceitos. O certificado do ponto de recarga traz a identidade dele no nome comum ou em um nome alternativo DNS (veja [Certificados](#certificates)). |
| Certificado raiz do sistema central | O caminho inteiro de `GanterLabConnector-<station>.pem`, o certificado raiz desta estação, que o ponto de recarga instala para confiar no sistema central, com o botão **Abrir a pasta**, que mostra o arquivo no gerenciador de arquivos do Windows. O botão funciona na janela da própria estação; num navegador em outro aparelho ele fica acinzentado e diz por quê. |

O cartão fica aberto enquanto o ponto de recarga não conectou desde que a estação
abriu, e se recolhe depois que ele conecta: continua na página para a próxima vez
que o ponto de recarga for configurado. Um ponto de recarga cujo certificado nenhuma
raiz instalada no Windows garante é recusado na primeira conexão e espera em
[Acesso a equipamentos](#equipment-access).

O arquivo é gravado na primeira vez que o sistema central inicia, quando um ponto de
recarga é registrado, e até lá o cartão diz isso. É o mesmo arquivo para todos os
pontos de recarga desta estação, e ele não muda quando o nome ou os endereços da estação
mudam (veja [O certificado raiz da estação](#the-stations-root-certificate)).

**Todo ponto de recarga que recebeu um arquivo de uma versão anterior precisa deste,
instalado uma vez.** No primeiro início desta versão, uma estação cujos pontos de recarga
podem ter um arquivo anterior mostra no cartão um aviso, **O arquivo desta estação
mudou**, só nessa execução. O aviso é um lembrete, não a instrução: instale o arquivo novo
uma vez em cada ponto de recarga de uma estação que já tinha pontos de recarga, o cartão
mostrando o aviso ou não. Um ponto de recarga que confere o nome do servidor passa a
aceitar a estação.

## Sistema central e portas {#central-system-and-ports}

| O quê | Valor |
|---|---|
| Versões de protocolo | OCPP **1.6**, **2.0**, **2.0.1** e **2.1** (negociação de subprotocolo no WebSocket; JSON) |
| Escuta | Todas as interfaces, porta TCP **19521**, só TLS |
| Endereço do ponto de recarga | `wss://<station-address>:19521/<charge-point-id>` |
| Identidade | A última parte do caminho do WebSocket é o id do ponto de recarga |

A escuta é sempre TLS; uma escuta em HTTP simples é recusada em qualquer lugar, exceto no
loopback, que existe só para testes em processo. Um ponto de recarga se registra
com a BootNotification dele (respondida com um intervalo de heartbeat de 60 segundos), e todo
crachá apresentado para autorização é aceito: o Ganter Lab observa a recarga, ele
não gerencia tarifas nem acesso.

## Certificados {#certificates}

O lado servidor do handshake TLS apresenta um certificado assinado pela raiz própria desta
estação (veja [O certificado raiz da estação](#the-stations-root-certificate)). Todo ponto
de recarga precisa apresentar um **certificado de cliente**:

1. Ele precisa ser confiável de um de dois jeitos: forma uma cadeia válida nesta máquina
   Windows, até uma raiz instalada nela, sem erros de política TLS; ou você aprovou este
   mesmo certificado em **Acesso a equipamentos** na página deste driver (abaixo). Nos dois
   casos ele precisa estar dentro das datas de validade. Uma conferência que falha recusa a
   conexão, e o diário registra qual conferência falhou.
2. O nome comum do titular dele, ou um nome alternativo de titular do tipo DNS, precisa **nomear o id
   do ponto de recarga** sob o qual ele conecta. Um certificado que nomeia um ponto de recarga
   diferente do que está no caminho da conexão é recusado, mesmo aprovado.

Um handshake sem certificado de cliente é descartado antes de qualquer dado passar.

### O certificado raiz da estação {#the-stations-root-certificate}

| O quê | Valor |
|---|---|
| A raiz | Criada uma vez por perfil, na primeira vez que o sistema central ou o servidor de rede LoRaWAN inicia. O assunto dela é `Ganter Lab Connector (<station>)`, em que `<station>` é o nome de rede nesse dia. Ela nunca expira e nunca é trocada sozinha: renomear o computador, mudar o nome de rede ou mudar os endereços da estação não a altera. |
| O arquivo | `GanterLabConnector-<station>.pem`, só a parte pública, na pasta de dados em `ua\pki\station`. É o mesmo arquivo para um ponto de recarga e para um gateway LoRaWAN, que o instala como `tc.trust`. |
| O certificado que o sistema central apresenta | Assinado por essa raiz. Ele traz o nome de rede da estação (o "Nome de rede" da configuração do servidor OPC UA embutido; o nome do computador enquanto está vazio), `localhost` e todos os endereços IPv4 da estação, e por isso um ponto de recarga que confere o nome do servidor (perfil de segurança 3) o aceita. Quando o nome de rede ou um endereço muda, só este certificado é emitido de novo, sozinho, sem nada a fazer no ponto de recarga. |
| O certificado do servidor OPC UA | Não é usado aqui. O servidor OPC UA embutido guarda o certificado dele para os clientes OPC UA. |

Uma raiz guardada que não pode mais ser aberta, por exemplo porque foi escrita por outra
conta do Windows, é substituída por uma nova. Todo ponto de recarga precisa então do
arquivo novo, uma vez, e o cartão diz isso.

### Acesso a equipamentos {#equipment-access}

Um ponto de recarga cujo certificado nenhuma raiz instalada no Windows garante, por ser
autoassinado ou emitido pela autoridade do próprio fabricante, não precisa dessa raiz
instalada neste computador. A primeira conexão dele é recusada, e o certificado espera em
**Acesso a equipamentos**, no fim da página do driver OCPP, o mesmo cartão da página do
driver OPC UA, até você decidir:

| Grupo | O que ele lista | O que você pode fazer |
|---|---|---|
| Esperando aprovação | Cada certificado recusado, sob o id do ponto de recarga com que ele conectou: a impressão digital SHA-256, quando tentou pela última vez e quantas vezes, e os detalhes (titular, emissor, nomes de domínio, datas de validade). | **Aprovar** admite o certificado a partir da próxima conexão do ponto de recarga. **Bloquear** continua recusando o certificado sem listá-lo aqui de novo. **Descartar todos os certificados pendentes** esvazia a lista sem aprovar nem bloquear nada. |
| Equipamentos aprovados | Os certificados que você aprovou ou importou, com quem decidiu e quando. | **Retirar a aprovação** encerra a conexão do ponto de recarga e devolve o certificado à lista. **Importar certificado** aprova o certificado público de um ponto de recarga antes da primeira conexão dele. |
| Equipamentos bloqueados | Os certificados que você bloqueou. Um certificado bloqueado é recusado mesmo que o Windows confie nele. | **Desbloquear** devolve o certificado à lista, sem aprová-lo. |

Cada certificado é aprovado por si, nunca a autoridade que o assinou, então um segundo
ponto de recarga do mesmo fabricante espera a própria aprovação. Confira a impressão
digital com a que o ponto de recarga informa antes de aprovar. Aprovar não muda qual ponto
de recarga o certificado é: ele continua admitido só sob o id do ponto de recarga que
nomeia, e só dentro das datas de validade. Um certificado em que o Windows já confia é
admitido como antes e nunca aparece aqui; nada é aprovado automaticamente.

As decisões ficam na pasta de dados da estação, em `ua\pki\ocpp`, e sobrevivem a um
reinício. Só um papel que pode configurar o Connector tem os comandos desenhados, e eles
agem só na janela da própria estação: um navegador em outro dispositivo lê o cartão sem
mudá-lo, e nenhuma ferramenta de agente aprova um certificado. A lista guarda até 100
certificados esperando aprovação; quando está cheia, um novo continua recusado mas não é
listado, e o cartão avisa.

## Campos de conexão {#connection-fields}

| Campo | O que é | Formato | Padrão |
|---|---|---|---|
| Identificador | O **id do ponto de recarga** que este dispositivo representa: o mesmo id que o carregador põe no fim da URL de conexão dele e carrega no certificado dele. | Texto livre, comparado ignorando maiúsculas e minúsculas. Vazio recai no nome higienizado do dispositivo. | vazio |

Não há campos de host, porta ou credencial: o carregador guarda os detalhes da
conexão, e esta estação só precisa saber a qual ponto de recarga o dispositivo se refere.
Também não há campos de intervalo de leitura. O OCPP é baseado em push (o ponto de recarga envia
mensagens MeterValues e StatusNotification na agenda dele) e as tags
se atualizam a partir dos últimos dados recebidos, num ciclo fixo de um segundo.

Um ponto de recarga que ainda não conectou, ou um conector que ainda não reportou,
portanto, **não tem leitura**, e não uma leitura que falhou. As tags dele ficam vazias e
nenhuma falha é registrada no diário: um valor que o ponto de recarga ainda não enviou é o
protocolo funcionando.

### A saúde do ponto de recarga {#the-charge-points-health}

Como um ponto de recarga envia os valores dele quando os tem, o silêncio das tags dele não
consegue separar um que ainda não reportou de um que sumiu. A saúde dele, o ponto na linha
dele na árvore e a coluna **Saúde** na página do driver, segue em vez disso a conexão dele
ao sistema central desta estação:

| Situação | Saúde |
|---|---|
| Configurado, e não conectou desde que a estação abriu | **Desconectado** |
| Conectado, ainda sem enviar nada | **Conectado** |
| Conectado e enviando | **Conectado**, ou **Parcialmente conectado** quando parte dos valores que ele enviou não se deixa ler |
| Caiu: parado, desligado da tomada ou isolado da rede | **Desconectado**, até ele conectar de novo |
| O sistema central sem escutar | **Desconectado** |
| Desabilitado | **Desabilitado** |

Enquanto o ponto de recarga está conectado, um conector que ainda não reportou não conta
contra ele. Por até dez segundos depois que uma mudança no ponto de recarga é salva, ou que
o Connector inicia, ele lê **Ainda não se sabe**: repor o dispositivo pode reiniciar o
sistema central, e o ponto de recarga leva um momento para conectar de novo.

## Tags {#tags}

Uma tag OCPP lê um **conector** do ponto de recarga (conector no sentido do
OCPP: uma posição de plugue, numerada a partir de 1). No OCPP 2.0, 2.0.1 e 2.1 o número é o do **EVSE**, porque
ali os conectores voltam a ser numerados a partir de 1 dentro de cada EVSE. Existem três tipos de tag, distinguidos pelo
**sufixo do nome da tag**, que é validado:

| O nome da tag termina em | O que ela lê | Tipo sensato |
|---|---|---|
| `Meter` | O valor de medição amostrado mais recente que o conector reportou (MeterValues do OCPP; no OCPP 2.x, também os valores que um TransactionEvent traz durante uma recarga). A unidade é o que o carregador enviar, tipicamente Wh. O servidor guarda as últimas 10 amostras e a tag lê a mais nova. Um conector que nunca reportou lê como valor vazio, não como zero. | Float ou Double |
| `Status` | O texto de estado do conector, da última StatusNotification (por exemplo `Available`, `Faulted`). No OCPP 2.x, um EVSE com mais de um conector lê o estado que mais diz entre eles: `Faulted` vence `Occupied`, `Occupied` vence `Reserved`, `Reserved` vence `Available`, e `Available` vence `Unavailable`. Um EVSE que ainda não reportou estado lê como valor vazio. | String |
| `Transaction` | O número da transação em curso no conector, que os comandos RemoteStopTransaction e GetTransactionStatus pedem: no OCPP 1.6, o número que esta estação deu à transação quando ela começou; no OCPP 2.x, o identificador da própria estação de recarga, exatamente como ela o enviou. É preenchido quando uma transação começa e esvaziado quando ela termina, então sem transação em curso a tag lê texto vazio. Até uma transação começar ou terminar depois que o ponto de recarga se conecta, ela lê como valor vazio, porque uma transação pode já estar em curso. | String |

Um nome sem nenhum desses sufixos é recusado pela validação: dê às tags nomes como
`Connector1Meter`, `Connector1Status` e `Connector1Transaction`.

| Campo | O que faz | Valores | Padrão |
|---|---|---|---|
| Connector | O número que esta tag lê: o do conector no OCPP 1.6, o do EVSE no OCPP 2.x. | 1 ou mais | 1 |
| Tipo de dado | O tipo OPC UA em que o valor é exposto. | Int32, Float, Double, String | Float |

Tags OCPP são **somente leitura**: o campo de acesso não oferece escolha gravável, e uma
escrita é recusada em vez de fingida. Comandar um ponto de recarga é um comando
próprio, descrito a seguir, e não um valor escrito numa tag.

## Comandos {#commands}

Um ponto de recarga é comandado além de lido. Cada dispositivo OCPP carrega os comandos
abaixo como **métodos no dispositivo**, dentro do espaço de endereços OPC UA desta estação, então
um cliente OPC UA conectado a esta estação dispara um comando chamando o método.

Todo comando recebe o **id do ponto de recarga** como primeiro argumento, e devolve a
resposta do próprio ponto de recarga como resultado.

| Comando | Outros argumentos | O que faz |
|---|---|---|
| ChangeAvailability | ConnectorId, Type (`Operative` ou `Inoperative`) | Coloca um conector em serviço ou fora de serviço. |
| ChangeConfiguration | Key, Value | Define uma chave de configuração no ponto de recarga (OCPP 1.6). |
| ClearCache | nenhum | Limpa o cache de autorização do ponto de recarga. |
| GetConfiguration | Key | Lê uma chave de configuração (OCPP 1.6). |
| RemoteStartTransaction | IdTag | Inicia uma sessão de recarga para um token. |
| RemoteStopTransaction | TransactionId | Encerra uma sessão em andamento. |
| GetTransactionStatus | TransactionId | Pergunta se uma transação ainda está rodando (OCPP 2.x). |
| Reset | nenhum | Reinicia o ponto de recarga. |
| UnlockConnector | ConnectorId | Libera o cabo de um conector. |
| SetChargingProfile | ConnectorId, Limit, NumberOfPhases | Define um limite de potência de recarga, em watts. ConnectorId 0 limita o ponto de recarga inteiro; outro número define o limite padrão das sessões que aquele conector carrega. |
| SetVariables | ComponentName, VariableName, AttributeType, AttributeValue | Define uma variável de um componente (OCPP 2.x). |
| GetVariables | ComponentName, VariableName, AttributeType | Lê uma variável de um componente (OCPP 2.x). |

O `AttributeType` é um entre `Actual`, `Target`, `MinSet`, `MaxSet`.

**De onde vem o TransactionId.** RemoteStopTransaction e GetTransactionStatus agem sobre uma transação, identificada pelo número dela. Leia esse número na tag `Transaction` do conector em que a sessão carrega (o EVSE, no OCPP 2.x), por exemplo `Connector1Transaction`, e passe-o como ele está. Texto vazio ali quer dizer que nenhuma transação está em curso naquele conector.

**Um catálogo, todas as versões.** Os comandos mantêm os nomes acima seja qual for a versão
que o ponto de recarga fala, e a estação envia cada um no formato que essa versão define. No
OCPP 2.0, 2.0.1 e 2.1 os conectores ficam agrupados em EVSEs, e o número passado como
ConnectorId indica o EVSE.

| Comando | No OCPP 1.6 | No OCPP 2.0, 2.0.1 e 2.1 |
|---|---|---|
| ChangeAvailability | Age sobre o conector indicado; 0 é o ponto de recarga inteiro. | Age sobre o EVSE indicado; 0 é a estação de recarga inteira. |
| RemoteStartTransaction | Envia o IdTag, e o ponto de recarga escolhe o conector. | Sai como RequestStartTransaction, com o IdTag como token central e um id de início próprio; a estação de recarga escolhe o EVSE. |
| RemoteStopTransaction | O TransactionId é o número que esta estação deu à sessão quando ela começou. | Sai como RequestStopTransaction; o TransactionId é o identificador da própria estação de recarga, repassado como texto. |
| Reset | Uma reinicialização completa. | Uma reinicialização imediata. |
| UnlockConnector | Libera o conector indicado. | Libera o primeiro conector do EVSE indicado. |
| SetChargingProfile | 0 define o perfil máximo do ponto de recarga; outro conector recebe um perfil padrão. | 0 define o perfil máximo da estação de recarga; outro EVSE recebe um perfil padrão. |
| ChangeConfiguration, GetConfiguration | Como na tabela acima. | Não existem nessas versões: a estação de recarga responde com um erro, e o comando falha. |
| GetTransactionStatus, SetVariables, GetVariables | Não existem nesta versão: o ponto de recarga responde com um erro, e o comando falha. | Como na tabela acima. |

**Esperar a resposta.** Um comando não está terminado quando a estação o enviou.
A estação segura a chamada aberta até o ponto de recarga responder exatamente à ordem que ela
enviou, casada pelo identificador de correlação que viaja com ela, e só então
relata sucesso e devolve a resposta. Três coisas a encerram de outro jeito, cada uma
relatada como falha com o seu motivo:

- O ponto de recarga não está conectado, ou a conexão dele não está aberta. Nada é enviado.
- O ponto de recarga responde com um erro OCPP, por exemplo um comando que ele não
  implementa. O código de erro é o motivo.
- Passam **30 segundos** sem resposta nenhuma. Um comando que ninguém respondeu é uma falha,
  nunca um sucesso.

Um comando disparado para um ponto de recarga que nenhum dispositivo carrega, ou que não está
conectado, é recusado de imediato, em vez de enfileirado.

## Descoberta {#discovery}

O **Descobrir** no driver OCPP lista os pontos de recarga **conectados no momento** ao
sistema central, e ler os canais de um candidato propõe uma tag `Meter`, uma
tag `Status` e uma tag `Transaction` por conector que o ponto de recarga tenha reportado até ali.

O **primeiro ponto de recarga é sempre configurado à mão**. Nada consegue conectar antes de
o sistema central escutar, e ele só escuta depois que existe um dispositivo OCPP aqui, então uma
varredura numa instalação sem nenhum ponto de recarga configurado não acha nada e diz isso.
Adicione esse primeiro dispositivo com o id sob o qual o carregador vai conectar; depois disso, um
carregador que já conectou pode ser descoberto. O fluxo geral de descoberta está descrito
na página [Connector](connector).

O id é comparado **ignorando maiúsculas e minúsculas**, no certificado, no caminho da
conexão e contra o dispositivo: um carregador que conecta como `cp-a` com um certificado
que nomeia `CP-A` é o mesmo ponto de recarga que um dispositivo cujo Identificador diz `CP-A`.

Um ponto de recarga que você já tem relê os conectores dele pela própria página: **Descobrir tags**, no cabeçalho do cartão **Tags** dele, oferece as tags `Meter`, `Status` e `Transaction` de cada conector que ele reportou enquanto conectado e para o qual o dispositivo ainda não tem tag (veja [Descobrir as tags de um dispositivo](connector-discovery#discovering-a-devices-tags)).
