Schema
Das TCPP-Nachrichtenformat 1.3.0
27 Endpunkte, jeder ein Request/Response-Paar, dazu
all.json, der Rahmen, den sie alle teilen. Jede Datei wird hier unter der
URL ausgeliefert, die ihre $id nennt; $ref löst sich damit ohne
Umschreiben auf.
Der Rahmen
Jede TCPP-Nachricht ist ein JSON-Objekt mit denselben fünf oder sechs Elementen der
obersten Ebene. Der Endpunkt bestimmt, was in record steht; alles darum
herum ist identisch, ob die Nachricht einen Ladevorgang meldet oder einen Ping
beantwortet.
| Element | In | Inhalt |
|---|---|---|
| tcpp | beide | Die Version, gegen die diese Nachricht geschrieben ist, als URL: https://tcpp.digital/schema/1.3.0/. |
| head | beide | Wer, an wen, wozu, wann und mit welchem Ergebnis. In allen Endpunkten gleich aufgebaut; unten beschrieben. |
| record | beide | Die Nutzlast, festgelegt vom Schema des jeweiligen Endpunkts. Das einzige Element, dessen Aufbau wechselt. |
| parsed | Response | Ergebnis je Element: eine Zuordnung von Pfaden im Request auf sechsstellige Fehlercodes; eine teilweise angenommene Nachricht sagt damit genau, welcher Teil gescheitert ist. |
| participants | beide | Weitere Beteiligte am Vorgang, jeweils mit Typ, Kennung und Rechten (read, control, push, broker …), optional mit Weiterleitendem und Genehmigendem. |
| references | beide | Die Nachrichten, auf die sich diese bezieht: je eine Referenzkennung, der vollständige head jener Nachricht und optional deren Signatur. Das macht einen Prozess aus seinen Datensätzen rekonstruierbar. |
Der Head
Zwölf Pflichtfelder. Eine Response wiederholt den Head des Requests mit umgekehrter
Richtung, vertauschtem Ursprung und Ziel und dem eigenen Ergebnis in
error_code.
| Feld | Typ | Bedeutung |
|---|---|---|
| record_type | string | Der Endpunkt: ping, charge_start, tariffs_list, … |
| record_direction | string | request, response oder internal. Auf jeden Request folgt eine Response; internal ist für Ausnahmen gedacht, etwa einen Fehler, den ein Gerät über sich selbst festhält. |
| record_udt | date-time | Universelles Datum mit Uhrzeit und Zeitversatz. |
| record_pagination | number | Der eigene Zähler des Senders für diesen Datensatz, ab 1. |
| record_version | string | Die TCPP-Version: 1.3.0. |
| origin_type | string(3) | Modultyp des Senders, siehe Tabelle unten. |
| origin_id | string | Kennung des Senders, mit Präfix für ihren Namensraum. |
| target_type | string(3) | Modultyp des Empfängers. |
| target_id | string | Kennung des Empfängers. |
| context_type | string(3) | Zu welcher Art Vorgang die Nachricht gehört: ein Prozesstyp, kein Modultyp. Darf leer sein. |
| context_id | string | Kennung dieses Vorgangs, gemeinsam für alle Nachrichten darin. Darf leer sein. |
| error_code | hex(6) | Das Ergebnis. 000000 im Request und in einer erfolgreichen Response. |
| error_text | string | Optionaler Klartext neben dem Code. |
Kennungen
Jede Kennung im Head (Ursprung, Ziel, Kontext, Beteiligte) trägt ein Präfix aus einem Buchstaben und einem Doppelpunkt, das ihren Namensraum benennt; damit ist nie unklar, was für ein Ding eine Kennung bezeichnet. Die ganze Kennung ist samt Präfix höchstens 120 Zeichen lang.
| Präfix | Namensraum | Beispiel |
|---|---|---|
| E: | EVSE-ID | E:DE*PID*E*IWS*00100017 |
| G: | GUID | G:90676293-fa28-49bd-81ba-1b58a0f62abd |
| D: | Domain-Namensraum | D:node.example.de |
| P: | privater Namensraum | P:ECS-HOST |
| I: | senderintern | I:slot-2 |
| H: | Hash | H:9f86d081884c7d… |
| N: | numerische Zählung | N:45330 |
| C: | Vertrags- oder Tarifkennung | C:DE-8AA-C12345-6 |
| V: | Fahrzeugkennung | V:WDD1234567A123456 |
| X: | undefiniert | X:legacy-7 |
Modultypen
Drei Großbuchstaben sagen, was ein Beteiligter ist. Der Typ nennt die Rolle im Protokoll, die Kennung das konkrete Gerät oder den konkreten Dienst.
Vertrauenswürdige Dienste
| Typ | Modul | Führt |
|---|---|---|
| TMH | Trusted Management Host | Schlüssel, Module, eMAIDs, Ladepunkte |
| TEH | Trusted Exchange Host | dynamische Daten: Status, Reservierungen |
| TAH | Trusted Archive Host | archivierte Dokumente und Datensätze |
Marktteilnehmer
| Typ | Modul | Anmerkung |
|---|---|---|
| MSP | eMobility Service Provider | eMSP |
| CPO | Charge Point Operator | sofern unabhängig vom MSP |
| LMP | Location Management Provider | Parkraum |
| FMP | Fleet Management Provider | Flotte und Logistik |
| ESP | Energy Supplier Provider | Energielieferant |
| SMS | Support Monitoring Service | technischer Service, Überwachung |
| SAS | Surveillance Authority Service | Behörden |
Ladepunkte und lokale Geräte
| Typ | Modul | Anmerkung |
|---|---|---|
| CSU | Charge Switch Unit | das Hauptgerät des Ladepunkts |
| CCU | Charge Central Unit | Zentrale eines Satellitensystems |
| LIU | Local Identification Unit | sofern unabhängig von der CSU |
| LDU | Local Display Unit | sofern unabhängig von der CSU |
| RIU | Remote Identification Unit | App, Telematik, externe Anzeige |
| RDU | Remote Display Unit | App, Telematik, externe Anzeige |
| PSU | Parking Space Unit | Parkhaus, Parkplatz |
| DEV | Device | jedes weitere Gerät |
Messung und Energiemanagement
| Typ | Modul | Anmerkung |
|---|---|---|
| SMG | Smart Meter Gateway | BSI TR-03109 |
| SML | Smart Meter Light | |
| ELM | Electric Meter | eigenständiger Zähler |
| EMU | Energy Management Unit | lokales Lastmanagement |
| GMU | Grid Energy Management Unit | netzseitiges Lastmanagement |
| BMU | Battery Management Unit | Batteriespeicher |
Kontexttypen
context_type benennt die Art des Vorgangs, zu dem eine Nachricht
gehört, und stammt aus einem eigenen Satz:
CRG Laden · ENG Energiesteuerung · MNT Wartung ·
INF Information · DRR Data Request Record · TFF Tarif.
Fehlercodes
Sechs Hexadezimalstellen, verwendet im Head, im elementweisen parsed-Block
einer Response und in Referenzen. Der Code wird in drei Teilen gelesen: die erste Stelle
ist die globale Klasse, die beiden folgenden der genaue Status, die letzten drei ein
modulspezifischer Status, FFF, wenn das Modul nicht bestimmt ist.
| Stelle 1 | Klasse |
|---|---|
| 0 | kein Fehler |
| 1 | nicht auswertbar |
| 2 | Head-Daten |
| 3 | Auswertung des Records |
| 4 | Aufbau des Records |
| 5 | Signaturumwandlung oder Zustellung |
| 6 | interner Softwarefehler |
| 7 | interner Hardwarefehler |
| F | unbekannt |
000000 bedeutet also Erfolg, FFFFFF einen unbekannten Fehler.
Eine Response, die den Head angenommen, aber ein Element einer Liste abgelehnt hat, sagt
das in parsed unter dem Pfad dieses Elements, statt die ganze Nachricht
scheitern zu lassen.
An den beiden Stellen wird der Code unterschiedlich geschrieben. Im
Head ist error_code ausschließlich großgeschriebenes Hexadezimal:
^[0-9A-F]{6}$. Die Werte in parsed sind großzügiger — beide
Schreibweisen und ein optionales führendes #. Ein Head mit
ffffff fällt durch die Prüfung, dieselbe Zeichenkette in
parsed nicht.
Signatur
Eine TCPP-Nachricht reist als Compact JWS mit alg: ES384,
also ECDSA über der NIST-Kurve P-384 mit SHA-384. Das oben gezeigte JSON-Objekt ist die
Nutzlast; der Empfänger dekodiert sie, prüft sie gegen den öffentlichen Schlüssel des
Senders und bewahrt Nachricht und Token gemeinsam auf.
Signiert werden die Bytes, wie sie erstellt wurden. Eine Prüfung muss über die empfangenen Bytes laufen, nie über eine neue Serialisierung des ausgewerteten Objekts: Schlüsselreihenfolge, Leerzeichen und Zahlenformat ändern sich dabei, und die Signatur übersteht das nicht.
JWS-Signaturen verwenden die feste R‖S-Kodierung nach IEEE P1363, die auch die Web Crypto
API eines Browsers erzeugt. Bibliotheken, die DER ausgeben, darunter
ecdsa.SignASN1 in Go, müssen zuvor umgewandelt werden, einschließlich der
Linksauffüllung einer zu kurzen Koordinate.
Eine Signatur kann auch innerhalb einer Nachricht mitgeführt werden: Jeder
Eintrag in references darf das jws des Datensatzes enthalten,
auf den er verweist. So lässt sich eine Kette von Datensätzen als ein Dokument
weitergeben und Glied für Glied prüfen. Dieses Element ist ein Objekt, nicht
die kompakte Zeichenkette, als die eine Nachricht reist: innerhalb eines Datensatzes
wird die Signatur in der JSON-Serialisierung von JWS geführt und bleibt damit als JSON
lesbar statt als eine undurchsichtige Zeile.
Endpunkte
27 Request/Response-Paare. Jeder Name verweist auf seine beiden Schemadateien.
Laden
| Endpunkt | Inhalt | Schema |
|---|---|---|
| charge_start | Eröffnung eines Ladevorgangs: Basisdaten der Sitzung und die beteiligten Rechtssubjekte. | Request · Response |
| charge_process | Der Vorgang selbst: Status, Ereignisse, Anzeige, Messkurven und Rechtssubjekte. | Request · Response |
| charge_event | Ein einzelnes Ereignis in einem laufenden Vorgang, bis hin zu dessen Ende. | Request · Response |
| emaid_get | Auflösung einer Vertragsidentität: per Karte, per Fahrzeug oder über eine andere Abfrageart. | Request · Response |
| tariffs_list | Tarife zu Ladepunkten, gesucht nach Kennung, nach Ort oder nach Ladegrenzen. | Request · Response |
Messung
| Endpunkt | Inhalt | Schema |
|---|---|---|
| measurement_create | Anlegen eines Measurement Configuration Record, der digitalen Selbstauskunft eines Zählers oder einer Ladesäule: was das Gerät ist, welche Hardware es erkannt hat, welche Software es fährt, auf welche Dokumente es verweist. | Request · Response |
| measurement_change | Ablösung eines Konfigurationsdatensatzes durch den nächsten; der alte bleibt auffindbar. | Request · Response |
| measurement_configuration | Abruf eines Konfigurationsdatensatzes, des Ankers, auf den sich jede spätere Nachricht über dieses Gerät bezieht. | Request · Response |
Identität, Schlüssel und Prüfung
| Endpunkt | Inhalt | Schema |
|---|---|---|
| key_get | Der öffentliche Schlüssel eines Moduls, damit dessen Signaturen prüfbar werden. | Request · Response |
| module_get | Was ein Modul ist: Typ, Kennung und die dazu hinterlegten Angaben. | Request · Response |
| verification_get | Die zu einem Modul festgehaltenen Prüfungen: wer was wann bescheinigt hat. | Request · Response |
| verification_set | Eintragen einer Prüfung zu einem Modul, unter Nennung des verantwortlichen Administrators. | Request · Response |
Konfiguration
| Endpunkt | Inhalt | Schema |
|---|---|---|
| parameters_get | Lesen benannter Parameter. | Request · Response |
| parameters_set | Schreiben von Parametern, unter Nennung der Administratoren, die es veranlasst haben. | Request · Response |
| parameters_delete | Entfernen von Parametern, ebenso zugeordnet. | Request · Response |
| parameters_list | Auflisten von Parametern über einen Bereich, mit Ergebnisgrenze. | Request · Response |
| trigger_set | Einrichten eines Triggers: Formeln, die ausgewertet werden, und Aktionen, wenn sie zutreffen. | Request · Response |
| trigger_get | Abruf eines einzelnen Triggers. | Request · Response |
| trigger_delete | Entfernen eines Triggers. | Request · Response |
| triggers_list | Auflisten von Triggern über einen Bereich. | Request · Response |
Betrieb
| Endpunkt | Inhalt | Schema |
|---|---|---|
| ping | Erreichbarkeit. Die kleinste Nachricht des Satzes und die erste, die man umsetzt. | Request · Response |
| status | Ein oder mehrere Statuswerte, gezählt und signiert, mit Verweis auf das, was sie beschreiben. | Request · Response |
| error | Fehler als eigener Datensatz: gezählt, referenziert und für sich meldbar. | Request · Response |
| display_output | Was eine Anzeige zeigen soll. | Request · Response |
| display_input | Was an ihr eingegeben wurde. | Request · Response |
Archiv
| Endpunkt | Inhalt | Schema |
|---|---|---|
| archive_list | Suche in archivierten Datensätzen nach Head und nach Inhalt, über einen Zeitraum und mit Ergebnisgrenze. | Request · Response |
| archive_get | Abruf eines archivierten Datensatzes, mit oder ohne die Signatur, unter der er abgelegt wurde. | Request · Response |
Das Rahmenschema
all.json ist das Basisformat, das die übrigen ausprägen: Head, die
Definitionen für Beteiligte und Referenzen und ein freier record. Dagegen
wird geprüft, wenn eine Nachricht gelesen werden muss, deren Endpunkt nicht
implementiert ist.
Die Dateien beziehen
Alle 55 Dateien, wie sie hier ausgeliefert werden, gibt es auch als ein Archiv. Der Referenzknoten bringt denselben Satz mit und liefert ihn unter denselben Pfaden aus; eine Implementierung lässt sich also gegen eine lokale Kopie entwickeln und unverändert auf die veröffentlichten URLs umstellen.