1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
//! The UTILMD qualifiers Modell 2 rides on, taken from the AHB rather than
//! from prose.
//!
//! Every constant here was read out of **UTILMD AHB Strom 2.2** (konsolidierte
//! Lesefassung mit Fehlerkorrekturen, 29.06.2026), Kapitel 11
//! „Anwendungsübersicht Ladevorgangscharfe bilanzielle Energiemengenzuordnung"
//! and Kapitel 4's Stammdaten tables. Nothing is inferred from a process
//! document: a qualifier that is not in the AHB is not in this module.
//!
//! # Read `SG10 CCI` by **both** data elements
//!
//! `CCI` carries a *Klassentyp* in DE 7059 and a *Merkmal* in DE 7037, and the
//! DE 7037 code space is reused across Klassentypen. Reading 7037 alone is the
//! defect this module exists to prevent — `ZE9` is „Modell 1" under
//! [`KLASSENTYP_ABWICKLUNGSMODELL`] and „Quartalsweise" elsewhere in the same
//! AHB. Ask [`abwicklungsmodell_from_cci`], which requires the pair.
/// `SG10 CCI` DE 7059 — Klassentyp **Abwicklungsmodell**.
pub const KLASSENTYP_ABWICKLUNGSMODELL: &str = "ZA2";
/// `SG10 CCI` DE 7037 under [`KLASSENTYP_ABWICKLUNGSMODELL`] — Modell 1,
/// „Bilanzierung an der Marktlokation".
pub const MERKMAL_MODELL_1: &str = "ZE9";
/// `SG10 CCI` DE 7037 under [`KLASSENTYP_ABWICKLUNGSMODELL`] — Modell 2,
/// „Bilanzierung im Bilanzierungsgebiet (BG) des LPB".
pub const MERKMAL_MODELL_2: &str = "ZF0";
/// `SG10 CCI` DE 7059 — Klassentyp **Bilanzierungsgebiet**.
///
/// On a 55238 the accompanying DE 7037 carries the BG itself, and AHB Bedingung
/// `[664]` fixes whose: „Es ist das BG des NB (LPB) anzugeben".
pub const KLASSENTYP_BILANZIERUNGSGEBIET: &str = "Z20";
/// `SG10 CCI` DE 7059 — Klassentyp **Stromverbrauchsart**.
pub const KLASSENTYP_STROMVERBRAUCHSART: &str = "Z17";
/// `SG10 CAV` DE 7111 — Verbrauchsart **E-Mobilität**.
///
/// This is the Verbrauchsart. [`ART_LADESAEULE`] is *not*: it answers a second,
/// narrower question in a second `CAV` of the same `SG10`.
pub const VERBRAUCHSART_E_MOBILITAET: &str = "ZE5";
/// `SG10 CAV` DE 7111 — Art der E-Mobilität: **Wallbox**.
pub const ART_WALLBOX: &str = "ZE6";
/// `SG10 CAV` DE 7111 — Art der E-Mobilität: **E-Mobilitätsladesäule**.
///
/// AHB Bedingung `[95]` makes the „Art der E-Mobilität" `CAV` a Muss only „wenn
/// in derselben SG10 das `CCI+Z17` (Stromverbrauchsart) `CAV+ZE5`
/// (E-Mobilität) vorhanden" — so it is a refinement of
/// [`VERBRAUCHSART_E_MOBILITAET`], never a substitute for it. A message that
/// carries `Z87` without `ZE5` states an Art with no Verbrauchsart and the
/// receiving AHB layer refuses it.
pub const ART_LADESAEULE: &str = "Z87";
/// `SG10 CAV` DE 7111 — Art der E-Mobilität: **Ladepark**.
pub const ART_LADEPARK: &str = "ZE7";
/// `SG5 LOC` DE 3227 — Marktlokation. DE 3225 carries the eleven-digit MaLo-ID.
pub const LOC_MARKTLOKATION: &str = "Z16";
/// `SG5 LOC` DE 3227 — MaBiS-Zählpunkt. DE 3225 carries a Zählpunktbezeichnung.
///
/// On a 55239 the VNB returns this beside [`LOC_MARKTLOKATION`]: AHB
/// Bedingung `[663]` says „Es ist die ID der Marktlokation und die ZPB des ZP der
/// NGZ anzugeben".
pub const LOC_MABIS_ZAEHLPUNKT: &str = "Z15";
/// `SG4 IDE` DE 7495 — Transaktion. DE 7402 carries the Vorgangsnummer.
pub const IDE_TRANSAKTION: &str = "24";
/// `SG4 DTM` DE 2005 — Datum Vertragsbeginn (the Modellwechseltermin).
pub const DTM_VERTRAGSBEGINN: &str = "92";
/// `SG4 DTM` DE 2005 — Bilanzierungsbeginn.
///
/// AHB Bedingung `[317]`: „Es ist derselbe Wert wie im DE2380 von `DTM+92`
/// (Datum Vertragsbeginn) einzutragen" — the two dates are one date on the
/// wire, and [`crate::uebergabestelle::Modellwechsel`] keeps them one in the
/// domain.
pub const DTM_BILANZIERUNGSBEGINN: &str = "158";
/// `SG4 STS` DE 9015 — Transaktionsgrund.
pub const STS_TRANSAKTIONSGRUND: &str = "7";
/// `SG4 STS` DE 9013 under [`STS_TRANSAKTIONSGRUND`] — Wechsel.
///
/// Both directions of the Modellwechsel carry it: an Anmeldung in Modell 2 and
/// an Abmeldung out of it are the same Transaktionsgrund, and what separates
/// them is the Prüfidentifikator.
pub const TRANSAKTIONSGRUND_WECHSEL: &str = "E03";
/// `SG4 STS` DE 9015 — Status der Antwort. DE 9013 carries the Antwortcode and
/// DE 1131 the EBD that publishes it.
pub const STS_STATUS_DER_ANTWORT: &str = "E01";
/// `SG6 RFF` DE 1153 — Prüfidentifikator. DE 1154 carries the PID itself.
pub const RFF_PRUEFIDENTIFIKATOR: &str = "Z13";
/// `SG6 RFF` DE 1153 — Transaktions-Referenznummer, echoing the request's
/// Vorgangsnummer on an answer.
pub const RFF_TRANSAKTIONSREFERENZ: &str = "TN";
/// `SG8 SEQ` DE 1229 — Daten der Marktlokation.
pub const SEQ_DATEN_MARKTLOKATION: &str = "Z01";
/// `SG8 SEQ` DE 1229 — OBIS-Daten der Marktlokation.
pub const SEQ_OBIS_DATEN: &str = "Z02";
/// `SG8 RFF` DE 1153 — Referenz auf die ID der Marktlokation.
pub const RFF_MARKTLOKATION: &str = "Z18";
/// `BGM` DE 1001 — Anmeldungen. All six Modellwechsel-PIDs carry it.
pub const BGM_ANMELDUNGEN: &str = "E01";
/// Which Abwicklungsmodell a `SG10 CCI` states, read from **both** data
/// elements.
///
/// Returns `None` when the Klassentyp is not
/// [`KLASSENTYP_ABWICKLUNGSMODELL`] — including when DE 7037 is a code this
/// module knows, because the same Merkmal means something else under another
/// Klassentyp.