Skip to main content

ocpp_types/v16/
standard.rs

1// @generated by ocpp-codegen from schemas/. Do not edit by hand -- run
2// `scripts/generate.sh` to regenerate; manual changes will be overwritten.
3
4//! Value sets the specification defines for fields its JSON schemas
5//! type as bare strings.
6//!
7//! A field like `Variable.name` or `SecurityEventNotification.type` is
8//! just `{"type": "string", "maxLength": N}` in the schema, with the
9//! permitted values listed in a specification appendix instead. Those
10//! appendix tables are vendored under `csv/` and generated into this
11//! module.
12//!
13//! Nothing here changes a wire type. OCPP permits vendor-specific
14//! values for these fields, so the message structs keep their
15//! `heapless::String` fields and these enums sit alongside:
16//!
17//! # Open and closed value sets
18//!
19//! The sets a deployment realistically extends -- components,
20//! variables, configuration keys -- are *open*: they carry an
21//! `Other` variant, so a third-party value survives a
22//! deserialize/serialize round trip. Use `from_wire_or_other` to
23//! accept any value, `from_wire` to ask whether a value is one the
24//! specification defines, and `is_standardized` to tell them apart
25//! afterwards. Their equality and hashing compare the wire string,
26//! so `Other("X")` and the `X` variant are one value.
27//!
28//! The rest are *closed*: one byte, `Copy`, and `from_wire`
29//! returning `None` is the only outcome for an unrecognized value.
30//! An open set is neither `Copy` nor one byte -- it is as wide as
31//! the field's `maxLength` -- which is why it is opt-in per set.
32//!
33//! ```ignore
34//! use ocpp_types::v21::common::Variable;
35//! use ocpp_types::v21::standard::VariableName;
36//!
37//! let variable = Variable {
38//!     name: heapless::String::try_from(VariableName::HeartbeatInterval.as_str()).unwrap(),
39//!     custom_data: None,
40//!     instance: None,
41//! };
42//! ```
43/// Returned by `FromStr` for a value the specification doesn't
44/// define.
45///
46/// Not in itself a protocol error: OCPP permits vendor-specific
47/// components, variables, configuration keys and security events,
48/// so receiving one of those is conformant. Use `from_wire` when an
49/// unrecognized value is expected and `Option` reads better than
50/// `Result`.
51#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
52pub struct UnknownValue;
53impl core::fmt::Display for UnknownValue {
54    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
55        f.write_str("not a value defined by this OCPP version's specification")
56    }
57}
58impl core::error::Error for UnknownValue {}
59/// Returned when a value is longer than the specification's
60/// `maxLength` for its field.
61///
62/// Only an open value set can produce this, and only from
63/// `from_wire_or_other`: a value too long for the field is not one the
64/// field could have carried, so it is rejected rather than truncated.
65#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
66pub struct ValueTooLong;
67impl core::fmt::Display for ValueTooLong {
68    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
69        f.write_str("longer than this field's maxLength in the specification")
70    }
71}
72impl core::error::Error for ValueTooLong {}
73/// Standardized configuration keys for `GetConfiguration` / `ChangeConfiguration`.
74///
75/// The schema types `key` as a plain string; the spec lists these in "Standard Configuration Key Names & Values", extended by the Security Whitepaper.
76///
77/// An *open* set: values the specification doesn't define are carried
78/// in [`Self::Other`] rather than rejected, so a deployment's own
79/// values survive a deserialize/serialize round trip.
80///
81/// Comparison and hashing go through the wire string, not the variant,
82/// so `Other("...")` holding a standardized value compares equal to
83/// that variant.
84#[derive(Debug, Clone)]
85pub enum ConfigurationKey {
86    /// If this key exists, the Charge Point supports Unknown Offline Authorization. If this key reports a value of true, Unknown Offline Authorization is enabled.
87    AllowOfflineTxForUnknownId,
88    /// If this key exists, the Charge Point supports an Authorization Cache. If this key reports a value of true, the Authorization Cache is enabled.
89    AuthorizationCacheEnabled,
90    /// Whether a remote request to start a transaction in the form of a RemoteStartTransaction.req message should be authorized beforehand like a local action to start a transaction.
91    AuthorizeRemoteTxRequests,
92    /// Number of times to blink Charge Point lighting when signalling.
93    BlinkRepeat,
94    /// Size (in seconds) of the clock-aligned data interval. This is the size (in seconds) of the set of evenly spaced aggregation intervals per day, starting at 00:00:00 (midnight).
95    ClockAlignedDataInterval,
96    /// Interval (from successful authorization) until incipient transaction is automatically cancelled, due to failure of EV driver to (correctly) insert the charging cable connector(s) into the appropriate socket(s).
97    ConnectionTimeOut,
98    /// The phase rotation per connector in respect to the connector's electrical meter (or if absent, the grid connection). Possible values per connector are RST, RTS, SRT, STR, TRS and TSR.
99    ConnectorPhaseRotation,
100    /// Maximum number of items in a ConnectorPhaseRotation Configuration Key.
101    ConnectorPhaseRotationMaxLength,
102    /// Maximum number of requested configuration keys in a GetConfiguration.req PDU.
103    GetConfigurationMaxKeys,
104    /// Interval (in seconds) of inactivity (no OCPP exchanges) with Central System after which the Charge Point should send a Heartbeat.req PDU.
105    HeartbeatInterval,
106    /// Percentage of maximum intensity at which to illuminate Charge Point lighting.
107    LightIntensity,
108    /// Whether the Charge Point, when offline, will start a transaction for locally-authorized identifiers.
109    LocalAuthorizeOffline,
110    /// Whether the Charge Point, when online, will start a transaction for locally-authorized identifiers without waiting for or requesting an Authorize.conf from the Central System.
111    LocalPreAuthorize,
112    /// Maximum energy in Wh delivered when an identifier is invalidated by the Central System after start of a transaction.
113    MaxEnergyOnInvalidId,
114    /// Clock-aligned measurand(s) to be included in a MeterValues.req PDU, every ClockAlignedDataInterval seconds.
115    MeterValuesAlignedData,
116    /// Maximum number of items in a MeterValuesAlignedData Configuration Key.
117    MeterValuesAlignedDataMaxLength,
118    /// Sampled measurands to be included in a MeterValues.req PDU, every MeterValueSampleInterval seconds. Where applicable, the Measurand is combined with the optional phase
119    MeterValuesSampledData,
120    /// Maximum number of items in a MeterValuesSampledData Configuration Key.
121    MeterValuesSampledDataMaxLength,
122    /// Interval (in seconds) between sampling of metering (or other) data, intended to be transmitted by MeterValues.req PDUs.
123    MeterValueSampleInterval,
124    /// The minimum duration that a Charge Point or Connector status is stable before a StatusNotification.req PDU is sent to the Central System.
125    MinimumStatusDuration,
126    /// The number of physical charging connectors of this Charge Point.
127    NumberOfConnectors,
128    /// Number of times to retry an unsuccessful reset of the Charge Point.
129    ResetRetries,
130    /// When set to true, the Charge Point SHALL administratively stop the transaction when the cable is unplugged from the EV.
131    StopTransactionOnEVSideDisconnect,
132    /// Whether the Charge Point will stop an ongoing transaction when it receives a non-Accepted authorization status in a StartTransaction.conf for this transaction.
133    StopTransactionOnInvalidId,
134    /// Clock-aligned periodic measurand(s) to be included in the TransactionData element of StopTransaction.req MeterValues.req PDU for every ClockAlignedDataInterval of the transaction.
135    StopTxnAlignedData,
136    /// Maximum number of items in a StopTxnAlignedData Configuration Key.
137    StopTxnAlignedDataMaxLength,
138    /// Sampled measurands to be included in the TransactionData element of StopTransaction.req PDU, every MeterValueSampleInterval seconds from the start of the transaction.
139    StopTxnSampledData,
140    /// Maximum number of items in a StopTxnSampledData Configuration Key.
141    StopTxnSampledDataMaxLength,
142    /// A list of supported Feature Profiles. Possible values are Core, FirmwareManagement, LocalAuthListManagement, Reservation, SmartCharging and RemoteTrigger.
143    SupportedFeatureProfiles,
144    /// Maximum number of items in a SupportedFeatureProfiles Configuration Key.
145    SupportedFeatureProfilesMaxLength,
146    /// How often the Charge Point should try to submit a transaction-related message when the Central System fails to process it.
147    TransactionMessageAttempts,
148    /// How long the Charge Point should wait before resubmitting a transaction-related message that the Central System failed to process.
149    TransactionMessageRetryInterval,
150    /// When set to true, the Charge Point SHALL unlock the cable on the Charge Point side when the cable is unplugged at the EV.
151    UnlockConnectorOnEVSideDisconnect,
152    /// Only relevant for websocket implementations. 0 disables client side websocket ping/pong. In this case there is either no ping/pong or the server initiates the ping and client responds with Pong.
153    WebSocketPingInterval,
154    /// Whether the Local Authorization List is enabled.
155    LocalAuthListEnabled,
156    /// Maximum number of identifications that can be stored in the Local Authorization List.
157    LocalAuthListMaxLength,
158    /// Maximum number of identifications that can be sent in a single SendLocalList.req.
159    SendLocalListMaxLength,
160    /// If this configuration key is present and set to true, Charge Point support reservations on connector 0.
161    ReserveConnectorZeroSupported,
162    /// Max StackLevel of a ChargingProfile. The number defined also indicates the max allowed number of installed charging schedules per Charging Profile Purposes.
163    ChargeProfileMaxStackLevel,
164    /// A list of supported quantities for use in a ChargingSchedule. Allowed values: Current and Power.
165    ChargingScheduleAllowedChargingRateUnit,
166    /// Maximum number of periods that may be defined per ChargingSchedule.
167    ChargingScheduleMaxPeriods,
168    /// If defined and true, this Charge Point support switching from 3 to 1 phase during a Transaction.
169    ConnectorSwitch3to1PhaseSupported,
170    /// Maximum number of Charging profiles installed at a time.
171    MaxChargingProfilesInstalled,
172    /// Whether a Charge Point should double-check whether a certificate is not revoked, in addition to the standard certificate chain check. When true, the Charge Point MUST verify the certificate against a Certificate Revocation List or an OCSP responder.
173    AdditionalRootCertificateCheck,
174    /// The basic authentication password used for HTTP Basic Authentication. Is write-only: reading it back returns no value. Minimal length is 16 bytes and it is not allowed to be set to an empty string.
175    AuthorizationKey,
176    /// This configuration key can be used to limit the size of the 'certificateChain' field from the CertificateSigned.req PDU. The value of this configuration key has a maximum limit of 10000 characters.
177    CertificateSignedMaxChainSize,
178    /// Maximum number of Root/CA certificates that can be installed in the Charge Point.
179    CertificateStoreMaxLength,
180    /// The Charge Point identity that is used as the value of the 'organizationName' field in the Certificate Signing Request when a Charge Point requests a new certificate.
181    CpoName,
182    /// This configuration key is used to set the security profile the Charge Point should use. It is not allowed to lower the security level of an existing connection.
183    SecurityProfile,
184    /// The transfer protocols supported for uploading a diagnostics or security log and for downloading firmware. Allowed values are FTP, FTPS, HTTP and HTTPS.
185    SupportedFileTransferProtocols,
186    /** A value this version's specification doesn't define -- typically a
187 vendor-specific one, which OCPP explicitly permits.
188
189 Bounded at 50 bytes, the same `maxLength` the wire field carries,
190 so anything the field can hold this can hold. Prefer
191 [`Self::from_wire_or_other`] over constructing this directly: it
192 returns the standardized variant when the value is one, keeping a
193 single representation per wire string.*/
194    Other(heapless::String<50usize>),
195}
196impl ConfigurationKey {
197    /// Every value this version's specification defines (50), in spec order.
198    ///
199    /// Does not include [`Self::Other`], which is unbounded in the
200    /// values it can hold.
201    pub const ALL: &'static [Self] = &[
202        Self::AllowOfflineTxForUnknownId,
203        Self::AuthorizationCacheEnabled,
204        Self::AuthorizeRemoteTxRequests,
205        Self::BlinkRepeat,
206        Self::ClockAlignedDataInterval,
207        Self::ConnectionTimeOut,
208        Self::ConnectorPhaseRotation,
209        Self::ConnectorPhaseRotationMaxLength,
210        Self::GetConfigurationMaxKeys,
211        Self::HeartbeatInterval,
212        Self::LightIntensity,
213        Self::LocalAuthorizeOffline,
214        Self::LocalPreAuthorize,
215        Self::MaxEnergyOnInvalidId,
216        Self::MeterValuesAlignedData,
217        Self::MeterValuesAlignedDataMaxLength,
218        Self::MeterValuesSampledData,
219        Self::MeterValuesSampledDataMaxLength,
220        Self::MeterValueSampleInterval,
221        Self::MinimumStatusDuration,
222        Self::NumberOfConnectors,
223        Self::ResetRetries,
224        Self::StopTransactionOnEVSideDisconnect,
225        Self::StopTransactionOnInvalidId,
226        Self::StopTxnAlignedData,
227        Self::StopTxnAlignedDataMaxLength,
228        Self::StopTxnSampledData,
229        Self::StopTxnSampledDataMaxLength,
230        Self::SupportedFeatureProfiles,
231        Self::SupportedFeatureProfilesMaxLength,
232        Self::TransactionMessageAttempts,
233        Self::TransactionMessageRetryInterval,
234        Self::UnlockConnectorOnEVSideDisconnect,
235        Self::WebSocketPingInterval,
236        Self::LocalAuthListEnabled,
237        Self::LocalAuthListMaxLength,
238        Self::SendLocalListMaxLength,
239        Self::ReserveConnectorZeroSupported,
240        Self::ChargeProfileMaxStackLevel,
241        Self::ChargingScheduleAllowedChargingRateUnit,
242        Self::ChargingScheduleMaxPeriods,
243        Self::ConnectorSwitch3to1PhaseSupported,
244        Self::MaxChargingProfilesInstalled,
245        Self::AdditionalRootCertificateCheck,
246        Self::AuthorizationKey,
247        Self::CertificateSignedMaxChainSize,
248        Self::CertificateStoreMaxLength,
249        Self::CpoName,
250        Self::SecurityProfile,
251        Self::SupportedFileTransferProtocols,
252    ];
253    /// This value as it appears on the wire.
254    pub fn as_str(&self) -> &str {
255        match self {
256            Self::AllowOfflineTxForUnknownId => "AllowOfflineTxForUnknownId",
257            Self::AuthorizationCacheEnabled => "AuthorizationCacheEnabled",
258            Self::AuthorizeRemoteTxRequests => "AuthorizeRemoteTxRequests",
259            Self::BlinkRepeat => "BlinkRepeat",
260            Self::ClockAlignedDataInterval => "ClockAlignedDataInterval",
261            Self::ConnectionTimeOut => "ConnectionTimeOut",
262            Self::ConnectorPhaseRotation => "ConnectorPhaseRotation",
263            Self::ConnectorPhaseRotationMaxLength => "ConnectorPhaseRotationMaxLength",
264            Self::GetConfigurationMaxKeys => "GetConfigurationMaxKeys",
265            Self::HeartbeatInterval => "HeartbeatInterval",
266            Self::LightIntensity => "LightIntensity",
267            Self::LocalAuthorizeOffline => "LocalAuthorizeOffline",
268            Self::LocalPreAuthorize => "LocalPreAuthorize",
269            Self::MaxEnergyOnInvalidId => "MaxEnergyOnInvalidId",
270            Self::MeterValuesAlignedData => "MeterValuesAlignedData",
271            Self::MeterValuesAlignedDataMaxLength => "MeterValuesAlignedDataMaxLength",
272            Self::MeterValuesSampledData => "MeterValuesSampledData",
273            Self::MeterValuesSampledDataMaxLength => "MeterValuesSampledDataMaxLength",
274            Self::MeterValueSampleInterval => "MeterValueSampleInterval",
275            Self::MinimumStatusDuration => "MinimumStatusDuration",
276            Self::NumberOfConnectors => "NumberOfConnectors",
277            Self::ResetRetries => "ResetRetries",
278            Self::StopTransactionOnEVSideDisconnect => {
279                "StopTransactionOnEVSideDisconnect"
280            }
281            Self::StopTransactionOnInvalidId => "StopTransactionOnInvalidId",
282            Self::StopTxnAlignedData => "StopTxnAlignedData",
283            Self::StopTxnAlignedDataMaxLength => "StopTxnAlignedDataMaxLength",
284            Self::StopTxnSampledData => "StopTxnSampledData",
285            Self::StopTxnSampledDataMaxLength => "StopTxnSampledDataMaxLength",
286            Self::SupportedFeatureProfiles => "SupportedFeatureProfiles",
287            Self::SupportedFeatureProfilesMaxLength => {
288                "SupportedFeatureProfilesMaxLength"
289            }
290            Self::TransactionMessageAttempts => "TransactionMessageAttempts",
291            Self::TransactionMessageRetryInterval => "TransactionMessageRetryInterval",
292            Self::UnlockConnectorOnEVSideDisconnect => {
293                "UnlockConnectorOnEVSideDisconnect"
294            }
295            Self::WebSocketPingInterval => "WebSocketPingInterval",
296            Self::LocalAuthListEnabled => "LocalAuthListEnabled",
297            Self::LocalAuthListMaxLength => "LocalAuthListMaxLength",
298            Self::SendLocalListMaxLength => "SendLocalListMaxLength",
299            Self::ReserveConnectorZeroSupported => "ReserveConnectorZeroSupported",
300            Self::ChargeProfileMaxStackLevel => "ChargeProfileMaxStackLevel",
301            Self::ChargingScheduleAllowedChargingRateUnit => {
302                "ChargingScheduleAllowedChargingRateUnit"
303            }
304            Self::ChargingScheduleMaxPeriods => "ChargingScheduleMaxPeriods",
305            Self::ConnectorSwitch3to1PhaseSupported => {
306                "ConnectorSwitch3to1PhaseSupported"
307            }
308            Self::MaxChargingProfilesInstalled => "MaxChargingProfilesInstalled",
309            Self::AdditionalRootCertificateCheck => "AdditionalRootCertificateCheck",
310            Self::AuthorizationKey => "AuthorizationKey",
311            Self::CertificateSignedMaxChainSize => "CertificateSignedMaxChainSize",
312            Self::CertificateStoreMaxLength => "CertificateStoreMaxLength",
313            Self::CpoName => "CpoName",
314            Self::SecurityProfile => "SecurityProfile",
315            Self::SupportedFileTransferProtocols => "SupportedFileTransferProtocols",
316            Self::Other(value) => value.as_str(),
317        }
318    }
319    /// Parses a wire value, returning `None` for values the
320    /// specification doesn't define.
321    ///
322    /// Use this to ask "is this one of the spec's values?". To accept
323    /// any value, use [`Self::from_wire_or_other`].
324    pub fn from_wire(value: &str) -> Option<Self> {
325        match value {
326            "AllowOfflineTxForUnknownId" => Some(Self::AllowOfflineTxForUnknownId),
327            "AuthorizationCacheEnabled" => Some(Self::AuthorizationCacheEnabled),
328            "AuthorizeRemoteTxRequests" => Some(Self::AuthorizeRemoteTxRequests),
329            "BlinkRepeat" => Some(Self::BlinkRepeat),
330            "ClockAlignedDataInterval" => Some(Self::ClockAlignedDataInterval),
331            "ConnectionTimeOut" => Some(Self::ConnectionTimeOut),
332            "ConnectorPhaseRotation" => Some(Self::ConnectorPhaseRotation),
333            "ConnectorPhaseRotationMaxLength" => {
334                Some(Self::ConnectorPhaseRotationMaxLength)
335            }
336            "GetConfigurationMaxKeys" => Some(Self::GetConfigurationMaxKeys),
337            "HeartbeatInterval" => Some(Self::HeartbeatInterval),
338            "LightIntensity" => Some(Self::LightIntensity),
339            "LocalAuthorizeOffline" => Some(Self::LocalAuthorizeOffline),
340            "LocalPreAuthorize" => Some(Self::LocalPreAuthorize),
341            "MaxEnergyOnInvalidId" => Some(Self::MaxEnergyOnInvalidId),
342            "MeterValuesAlignedData" => Some(Self::MeterValuesAlignedData),
343            "MeterValuesAlignedDataMaxLength" => {
344                Some(Self::MeterValuesAlignedDataMaxLength)
345            }
346            "MeterValuesSampledData" => Some(Self::MeterValuesSampledData),
347            "MeterValuesSampledDataMaxLength" => {
348                Some(Self::MeterValuesSampledDataMaxLength)
349            }
350            "MeterValueSampleInterval" => Some(Self::MeterValueSampleInterval),
351            "MinimumStatusDuration" => Some(Self::MinimumStatusDuration),
352            "NumberOfConnectors" => Some(Self::NumberOfConnectors),
353            "ResetRetries" => Some(Self::ResetRetries),
354            "StopTransactionOnEVSideDisconnect" => {
355                Some(Self::StopTransactionOnEVSideDisconnect)
356            }
357            "StopTransactionOnInvalidId" => Some(Self::StopTransactionOnInvalidId),
358            "StopTxnAlignedData" => Some(Self::StopTxnAlignedData),
359            "StopTxnAlignedDataMaxLength" => Some(Self::StopTxnAlignedDataMaxLength),
360            "StopTxnSampledData" => Some(Self::StopTxnSampledData),
361            "StopTxnSampledDataMaxLength" => Some(Self::StopTxnSampledDataMaxLength),
362            "SupportedFeatureProfiles" => Some(Self::SupportedFeatureProfiles),
363            "SupportedFeatureProfilesMaxLength" => {
364                Some(Self::SupportedFeatureProfilesMaxLength)
365            }
366            "TransactionMessageAttempts" => Some(Self::TransactionMessageAttempts),
367            "TransactionMessageRetryInterval" => {
368                Some(Self::TransactionMessageRetryInterval)
369            }
370            "UnlockConnectorOnEVSideDisconnect" => {
371                Some(Self::UnlockConnectorOnEVSideDisconnect)
372            }
373            "WebSocketPingInterval" => Some(Self::WebSocketPingInterval),
374            "LocalAuthListEnabled" => Some(Self::LocalAuthListEnabled),
375            "LocalAuthListMaxLength" => Some(Self::LocalAuthListMaxLength),
376            "SendLocalListMaxLength" => Some(Self::SendLocalListMaxLength),
377            "ReserveConnectorZeroSupported" => Some(Self::ReserveConnectorZeroSupported),
378            "ChargeProfileMaxStackLevel" => Some(Self::ChargeProfileMaxStackLevel),
379            "ChargingScheduleAllowedChargingRateUnit" => {
380                Some(Self::ChargingScheduleAllowedChargingRateUnit)
381            }
382            "ChargingScheduleMaxPeriods" => Some(Self::ChargingScheduleMaxPeriods),
383            "ConnectorSwitch3to1PhaseSupported" => {
384                Some(Self::ConnectorSwitch3to1PhaseSupported)
385            }
386            "MaxChargingProfilesInstalled" => Some(Self::MaxChargingProfilesInstalled),
387            "AdditionalRootCertificateCheck" => {
388                Some(Self::AdditionalRootCertificateCheck)
389            }
390            "AuthorizationKey" => Some(Self::AuthorizationKey),
391            "CertificateSignedMaxChainSize" => Some(Self::CertificateSignedMaxChainSize),
392            "CertificateStoreMaxLength" => Some(Self::CertificateStoreMaxLength),
393            "CpoName" => Some(Self::CpoName),
394            "SecurityProfile" => Some(Self::SecurityProfile),
395            "SupportedFileTransferProtocols" => {
396                Some(Self::SupportedFileTransferProtocols)
397            }
398            _ => None,
399        }
400    }
401    /// Parses any wire value, falling back to [`Self::Other`].
402    ///
403    /// Fails only if `value` is longer than the specification's
404    /// `maxLength` for this field, in which case it isn't a value the
405    /// field could have carried in the first place.
406    pub fn from_wire_or_other(value: &str) -> Result<Self, ValueTooLong> {
407        if let Some(standardized) = Self::from_wire(value) {
408            return Ok(standardized);
409        }
410        heapless::String::try_from(value).map(Self::Other).map_err(|_| ValueTooLong)
411    }
412    /// Whether this is one of the values the specification defines,
413    /// as opposed to a vendor's own.
414    pub fn is_standardized(&self) -> bool {
415        !matches!(self, Self::Other(_))
416    }
417    /// `R` (read-only), `RW` (read/write), or `W`, as stated by the spec.
418    pub fn accessibility(&self) -> Option<&'static str> {
419        match self {
420            Self::AllowOfflineTxForUnknownId => Some("RW"),
421            Self::AuthorizationCacheEnabled => Some("RW"),
422            Self::AuthorizeRemoteTxRequests => Some("R or RW"),
423            Self::BlinkRepeat => Some("RW"),
424            Self::ClockAlignedDataInterval => Some("RW"),
425            Self::ConnectionTimeOut => Some("RW"),
426            Self::ConnectorPhaseRotation => Some("RW"),
427            Self::ConnectorPhaseRotationMaxLength => Some("R"),
428            Self::GetConfigurationMaxKeys => Some("R"),
429            Self::HeartbeatInterval => Some("RW"),
430            Self::LightIntensity => Some("RW"),
431            Self::LocalAuthorizeOffline => Some("RW"),
432            Self::LocalPreAuthorize => Some("RW"),
433            Self::MaxEnergyOnInvalidId => Some("RW"),
434            Self::MeterValuesAlignedData => Some("RW"),
435            Self::MeterValuesAlignedDataMaxLength => Some("R"),
436            Self::MeterValuesSampledData => Some("RW"),
437            Self::MeterValuesSampledDataMaxLength => Some("R"),
438            Self::MeterValueSampleInterval => Some("RW"),
439            Self::MinimumStatusDuration => Some("RW"),
440            Self::NumberOfConnectors => Some("R"),
441            Self::ResetRetries => Some("RW"),
442            Self::StopTransactionOnEVSideDisconnect => Some("RW"),
443            Self::StopTransactionOnInvalidId => Some("RW"),
444            Self::StopTxnAlignedData => Some("RW"),
445            Self::StopTxnAlignedDataMaxLength => Some("R"),
446            Self::StopTxnSampledData => Some("RW"),
447            Self::StopTxnSampledDataMaxLength => Some("R"),
448            Self::SupportedFeatureProfiles => Some("R"),
449            Self::SupportedFeatureProfilesMaxLength => Some("R"),
450            Self::TransactionMessageAttempts => Some("RW"),
451            Self::TransactionMessageRetryInterval => Some("RW"),
452            Self::UnlockConnectorOnEVSideDisconnect => Some("RW"),
453            Self::WebSocketPingInterval => Some("RW"),
454            Self::LocalAuthListEnabled => Some("RW"),
455            Self::LocalAuthListMaxLength => Some("R"),
456            Self::SendLocalListMaxLength => Some("R"),
457            Self::ReserveConnectorZeroSupported => Some("R"),
458            Self::ChargeProfileMaxStackLevel => Some("R"),
459            Self::ChargingScheduleAllowedChargingRateUnit => Some("R"),
460            Self::ChargingScheduleMaxPeriods => Some("R"),
461            Self::ConnectorSwitch3to1PhaseSupported => Some("R"),
462            Self::MaxChargingProfilesInstalled => Some("R"),
463            Self::AdditionalRootCertificateCheck => Some("R"),
464            Self::AuthorizationKey => Some("RW"),
465            Self::CertificateSignedMaxChainSize => Some("R"),
466            Self::CertificateStoreMaxLength => Some("R"),
467            Self::CpoName => Some("RW"),
468            Self::SecurityProfile => Some("RW"),
469            Self::SupportedFileTransferProtocols => Some("R"),
470            Self::Other(_) => None,
471        }
472    }
473    /// The value's type as stated by the spec (e.g. `integer`, `boolean`, `CSL`).
474    pub fn value_type(&self) -> Option<&'static str> {
475        match self {
476            Self::AllowOfflineTxForUnknownId => Some("boolean"),
477            Self::AuthorizationCacheEnabled => Some("boolean"),
478            Self::AuthorizeRemoteTxRequests => Some("boolean"),
479            Self::BlinkRepeat => Some("integer"),
480            Self::ClockAlignedDataInterval => Some("integer"),
481            Self::ConnectionTimeOut => Some("integer"),
482            Self::ConnectorPhaseRotation => Some("CSL"),
483            Self::ConnectorPhaseRotationMaxLength => Some("integer"),
484            Self::GetConfigurationMaxKeys => Some("integer"),
485            Self::HeartbeatInterval => Some("integer"),
486            Self::LightIntensity => Some("integer"),
487            Self::LocalAuthorizeOffline => Some("boolean"),
488            Self::LocalPreAuthorize => Some("boolean"),
489            Self::MaxEnergyOnInvalidId => Some("integer"),
490            Self::MeterValuesAlignedData => Some("CSL"),
491            Self::MeterValuesAlignedDataMaxLength => Some("integer"),
492            Self::MeterValuesSampledData => Some("CSL"),
493            Self::MeterValuesSampledDataMaxLength => Some("integer"),
494            Self::MeterValueSampleInterval => Some("integer"),
495            Self::MinimumStatusDuration => Some("integer"),
496            Self::NumberOfConnectors => Some("integer"),
497            Self::ResetRetries => Some("integer"),
498            Self::StopTransactionOnEVSideDisconnect => Some("boolean"),
499            Self::StopTransactionOnInvalidId => Some("boolean"),
500            Self::StopTxnAlignedData => Some("CSL"),
501            Self::StopTxnAlignedDataMaxLength => Some("integer"),
502            Self::StopTxnSampledData => Some("CSL"),
503            Self::StopTxnSampledDataMaxLength => Some("integer"),
504            Self::SupportedFeatureProfiles => Some("CSL"),
505            Self::SupportedFeatureProfilesMaxLength => Some("integer"),
506            Self::TransactionMessageAttempts => Some("integer"),
507            Self::TransactionMessageRetryInterval => Some("integer"),
508            Self::UnlockConnectorOnEVSideDisconnect => Some("boolean"),
509            Self::WebSocketPingInterval => Some("integer"),
510            Self::LocalAuthListEnabled => Some("boolean"),
511            Self::LocalAuthListMaxLength => Some("integer"),
512            Self::SendLocalListMaxLength => Some("integer"),
513            Self::ReserveConnectorZeroSupported => Some("boolean"),
514            Self::ChargeProfileMaxStackLevel => Some("integer"),
515            Self::ChargingScheduleAllowedChargingRateUnit => Some("CSL"),
516            Self::ChargingScheduleMaxPeriods => Some("integer"),
517            Self::ConnectorSwitch3to1PhaseSupported => Some("boolean"),
518            Self::MaxChargingProfilesInstalled => Some("integer"),
519            Self::AdditionalRootCertificateCheck => Some("boolean"),
520            Self::AuthorizationKey => Some("string"),
521            Self::CertificateSignedMaxChainSize => Some("integer"),
522            Self::CertificateStoreMaxLength => Some("integer"),
523            Self::CpoName => Some("string"),
524            Self::SecurityProfile => Some("integer"),
525            Self::SupportedFileTransferProtocols => Some("CSL"),
526            Self::Other(_) => None,
527        }
528    }
529    /// Whether the spec requires every Charging Station to support this key.
530    pub fn is_required(&self) -> bool {
531        match self {
532            Self::AllowOfflineTxForUnknownId => false,
533            Self::AuthorizationCacheEnabled => false,
534            Self::AuthorizeRemoteTxRequests => true,
535            Self::BlinkRepeat => false,
536            Self::ClockAlignedDataInterval => true,
537            Self::ConnectionTimeOut => true,
538            Self::ConnectorPhaseRotation => true,
539            Self::ConnectorPhaseRotationMaxLength => false,
540            Self::GetConfigurationMaxKeys => true,
541            Self::HeartbeatInterval => true,
542            Self::LightIntensity => false,
543            Self::LocalAuthorizeOffline => true,
544            Self::LocalPreAuthorize => true,
545            Self::MaxEnergyOnInvalidId => false,
546            Self::MeterValuesAlignedData => true,
547            Self::MeterValuesAlignedDataMaxLength => false,
548            Self::MeterValuesSampledData => true,
549            Self::MeterValuesSampledDataMaxLength => false,
550            Self::MeterValueSampleInterval => true,
551            Self::MinimumStatusDuration => false,
552            Self::NumberOfConnectors => true,
553            Self::ResetRetries => true,
554            Self::StopTransactionOnEVSideDisconnect => true,
555            Self::StopTransactionOnInvalidId => true,
556            Self::StopTxnAlignedData => true,
557            Self::StopTxnAlignedDataMaxLength => false,
558            Self::StopTxnSampledData => true,
559            Self::StopTxnSampledDataMaxLength => false,
560            Self::SupportedFeatureProfiles => true,
561            Self::SupportedFeatureProfilesMaxLength => false,
562            Self::TransactionMessageAttempts => true,
563            Self::TransactionMessageRetryInterval => true,
564            Self::UnlockConnectorOnEVSideDisconnect => true,
565            Self::WebSocketPingInterval => false,
566            Self::LocalAuthListEnabled => true,
567            Self::LocalAuthListMaxLength => true,
568            Self::SendLocalListMaxLength => true,
569            Self::ReserveConnectorZeroSupported => false,
570            Self::ChargeProfileMaxStackLevel => true,
571            Self::ChargingScheduleAllowedChargingRateUnit => true,
572            Self::ChargingScheduleMaxPeriods => true,
573            Self::ConnectorSwitch3to1PhaseSupported => false,
574            Self::MaxChargingProfilesInstalled => true,
575            Self::AdditionalRootCertificateCheck => true,
576            Self::AuthorizationKey => true,
577            Self::CertificateSignedMaxChainSize => false,
578            Self::CertificateStoreMaxLength => false,
579            Self::CpoName => true,
580            Self::SecurityProfile => true,
581            Self::SupportedFileTransferProtocols => true,
582            Self::Other(_) => false,
583        }
584    }
585    /// The feature profile that defines the key (e.g. `Core`, `SmartCharging`, `Security`).
586    pub fn feature_profile(&self) -> Option<&'static str> {
587        match self {
588            Self::AllowOfflineTxForUnknownId => Some("Core"),
589            Self::AuthorizationCacheEnabled => Some("Core"),
590            Self::AuthorizeRemoteTxRequests => Some("Core"),
591            Self::BlinkRepeat => Some("Core"),
592            Self::ClockAlignedDataInterval => Some("Core"),
593            Self::ConnectionTimeOut => Some("Core"),
594            Self::ConnectorPhaseRotation => Some("Core"),
595            Self::ConnectorPhaseRotationMaxLength => Some("Core"),
596            Self::GetConfigurationMaxKeys => Some("Core"),
597            Self::HeartbeatInterval => Some("Core"),
598            Self::LightIntensity => Some("Core"),
599            Self::LocalAuthorizeOffline => Some("Core"),
600            Self::LocalPreAuthorize => Some("Core"),
601            Self::MaxEnergyOnInvalidId => Some("Core"),
602            Self::MeterValuesAlignedData => Some("Core"),
603            Self::MeterValuesAlignedDataMaxLength => Some("Core"),
604            Self::MeterValuesSampledData => Some("Core"),
605            Self::MeterValuesSampledDataMaxLength => Some("Core"),
606            Self::MeterValueSampleInterval => Some("Core"),
607            Self::MinimumStatusDuration => Some("Core"),
608            Self::NumberOfConnectors => Some("Core"),
609            Self::ResetRetries => Some("Core"),
610            Self::StopTransactionOnEVSideDisconnect => Some("Core"),
611            Self::StopTransactionOnInvalidId => Some("Core"),
612            Self::StopTxnAlignedData => Some("Core"),
613            Self::StopTxnAlignedDataMaxLength => Some("Core"),
614            Self::StopTxnSampledData => Some("Core"),
615            Self::StopTxnSampledDataMaxLength => Some("Core"),
616            Self::SupportedFeatureProfiles => Some("Core"),
617            Self::SupportedFeatureProfilesMaxLength => Some("Core"),
618            Self::TransactionMessageAttempts => Some("Core"),
619            Self::TransactionMessageRetryInterval => Some("Core"),
620            Self::UnlockConnectorOnEVSideDisconnect => Some("Core"),
621            Self::WebSocketPingInterval => Some("Core"),
622            Self::LocalAuthListEnabled => Some("LocalAuthListManagement"),
623            Self::LocalAuthListMaxLength => Some("LocalAuthListManagement"),
624            Self::SendLocalListMaxLength => Some("LocalAuthListManagement"),
625            Self::ReserveConnectorZeroSupported => Some("Reservation"),
626            Self::ChargeProfileMaxStackLevel => Some("SmartCharging"),
627            Self::ChargingScheduleAllowedChargingRateUnit => Some("SmartCharging"),
628            Self::ChargingScheduleMaxPeriods => Some("SmartCharging"),
629            Self::ConnectorSwitch3to1PhaseSupported => Some("SmartCharging"),
630            Self::MaxChargingProfilesInstalled => Some("SmartCharging"),
631            Self::AdditionalRootCertificateCheck => Some("Security"),
632            Self::AuthorizationKey => Some("Security"),
633            Self::CertificateSignedMaxChainSize => Some("Security"),
634            Self::CertificateStoreMaxLength => Some("Security"),
635            Self::CpoName => Some("Security"),
636            Self::SecurityProfile => Some("Security"),
637            Self::SupportedFileTransferProtocols => Some("Security"),
638            Self::Other(_) => None,
639        }
640    }
641}
642impl core::fmt::Display for ConfigurationKey {
643    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
644        f.write_str(self.as_str())
645    }
646}
647impl core::str::FromStr for ConfigurationKey {
648    type Err = ValueTooLong;
649    fn from_str(value: &str) -> Result<Self, Self::Err> {
650        Self::from_wire_or_other(value)
651    }
652}
653impl PartialEq for ConfigurationKey {
654    fn eq(&self, other: &Self) -> bool {
655        self.as_str() == other.as_str()
656    }
657}
658impl Eq for ConfigurationKey {}
659impl core::hash::Hash for ConfigurationKey {
660    fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
661        self.as_str().hash(state);
662    }
663}
664impl PartialOrd for ConfigurationKey {
665    fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
666        Some(self.cmp(other))
667    }
668}
669impl Ord for ConfigurationKey {
670    fn cmp(&self, other: &Self) -> core::cmp::Ordering {
671        self.as_str().cmp(other.as_str())
672    }
673}
674#[cfg(feature = "serde")]
675impl serde::Serialize for ConfigurationKey {
676    fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
677        serializer.serialize_str(self.as_str())
678    }
679}
680#[cfg(feature = "serde")]
681impl<'de> serde::Deserialize<'de> for ConfigurationKey {
682    fn deserialize<D: serde::Deserializer<'de>>(
683        deserializer: D,
684    ) -> Result<Self, D::Error> {
685        struct Visitor;
686        impl<'v> serde::de::Visitor<'v> for Visitor {
687            type Value = ConfigurationKey;
688            fn expecting(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
689                f.write_str("a ConfigurationKey string")
690            }
691            fn visit_str<E: serde::de::Error>(
692                self,
693                value: &str,
694            ) -> Result<Self::Value, E> {
695                ConfigurationKey::from_wire_or_other(value)
696                    .map_err(serde::de::Error::custom)
697            }
698        }
699        deserializer.deserialize_str(Visitor)
700    }
701}
702/// Standardized `SecurityEventNotification.type` values, from the 1.6 Security Whitepaper.
703///
704/// A *closed* set: it holds only the values the specification
705/// defines. The wire field is a string, so a deployment can still
706/// send something else -- `from_wire` returns `None` for that,
707/// which is not by itself a protocol error.
708#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
709#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
710pub enum SecurityEvent {
711    /// The Charge Point firmware is updated
712    FirmwareUpdated,
713    /// The authentication credentials provided by the Charge Point were rejected by the Central System
714    FailedToAuthenticateAtCsms,
715    /// The authentication credentials provided by the Central System were rejected by the Charge Point
716    CsmsFailedToAuthenticate,
717    /// The system time on the Charge Point was changed
718    SettingSystemTime,
719    /// The Charge Point has booted
720    StartupOfTheDevice,
721    /// The Charge Point was rebooted or reset
722    ResetOrReboot,
723    /// The security log was cleared
724    SecurityLogWasCleared,
725    /// Security parameters, such as keys or the security profile used, were changed
726    ReconfigurationOfSecurityParameters,
727    /// The Flash or RAM memory of the Charge Point is getting full
728    MemoryExhaustion,
729    /// The Charge Point has received messages that are not valid OCPP messages, if signed messages, signage invalid/incorrect
730    InvalidMessages,
731    /// The Charge Point has received a replayed message (other than the Central System trying to resend a message because there was for example a network problem)
732    AttemptedReplayAttacks,
733    /// The physical tamper detection sensor was triggered
734    TamperDetectionActivated,
735    /// The firmware signature is not valid
736    InvalidFirmwareSignature,
737    /// The certificate used to verify the firmware signature is not valid
738    InvalidFirmwareSigningCertificate,
739    /// The certificate that the Central System uses was not valid or could not be verified
740    InvalidCsmsCertificate,
741    /// The certificate sent to the Charge Point using the CertificateSigned.req message is not a valid certificate
742    InvalidChargePointCertificate,
743    /// The TLS version used by the Central System is lower than 1.2 and is not allowed by the security specification
744    InvalidTLSVersion,
745    /// The Central System did only allow connections using TLS cipher suites that are not allowed by the security specification
746    InvalidTLSCipherSuite,
747    /// Successful login to the local maintenance interface. It is recommended to include information like the user identification and the origin of the login attempt in the techInfo field
748    MaintenanceLoginAccepted,
749    /// Failed login attempt to the local maintenance interface. It is recommended to include information like the user identification and the origin of the login attempt in the techInfo field
750    MaintenanceLoginFailed,
751}
752impl SecurityEvent {
753    /// Every value this version's specification defines (20), in spec order.
754    pub const ALL: &'static [Self] = &[
755        Self::FirmwareUpdated,
756        Self::FailedToAuthenticateAtCsms,
757        Self::CsmsFailedToAuthenticate,
758        Self::SettingSystemTime,
759        Self::StartupOfTheDevice,
760        Self::ResetOrReboot,
761        Self::SecurityLogWasCleared,
762        Self::ReconfigurationOfSecurityParameters,
763        Self::MemoryExhaustion,
764        Self::InvalidMessages,
765        Self::AttemptedReplayAttacks,
766        Self::TamperDetectionActivated,
767        Self::InvalidFirmwareSignature,
768        Self::InvalidFirmwareSigningCertificate,
769        Self::InvalidCsmsCertificate,
770        Self::InvalidChargePointCertificate,
771        Self::InvalidTLSVersion,
772        Self::InvalidTLSCipherSuite,
773        Self::MaintenanceLoginAccepted,
774        Self::MaintenanceLoginFailed,
775    ];
776    /// This value as it appears on the wire.
777    pub const fn as_str(&self) -> &'static str {
778        match self {
779            Self::FirmwareUpdated => "FirmwareUpdated",
780            Self::FailedToAuthenticateAtCsms => "FailedToAuthenticateAtCsms",
781            Self::CsmsFailedToAuthenticate => "CsmsFailedToAuthenticate",
782            Self::SettingSystemTime => "SettingSystemTime",
783            Self::StartupOfTheDevice => "StartupOfTheDevice",
784            Self::ResetOrReboot => "ResetOrReboot",
785            Self::SecurityLogWasCleared => "SecurityLogWasCleared",
786            Self::ReconfigurationOfSecurityParameters => {
787                "ReconfigurationOfSecurityParameters"
788            }
789            Self::MemoryExhaustion => "MemoryExhaustion",
790            Self::InvalidMessages => "InvalidMessages",
791            Self::AttemptedReplayAttacks => "AttemptedReplayAttacks",
792            Self::TamperDetectionActivated => "TamperDetectionActivated",
793            Self::InvalidFirmwareSignature => "InvalidFirmwareSignature",
794            Self::InvalidFirmwareSigningCertificate => {
795                "InvalidFirmwareSigningCertificate"
796            }
797            Self::InvalidCsmsCertificate => "InvalidCsmsCertificate",
798            Self::InvalidChargePointCertificate => "InvalidChargePointCertificate",
799            Self::InvalidTLSVersion => "InvalidTLSVersion",
800            Self::InvalidTLSCipherSuite => "InvalidTLSCipherSuite",
801            Self::MaintenanceLoginAccepted => "MaintenanceLoginAccepted",
802            Self::MaintenanceLoginFailed => "MaintenanceLoginFailed",
803        }
804    }
805    /// Parses a wire value, returning `None` for values the
806    /// specification doesn't define (e.g. a vendor's own).
807    pub fn from_wire(value: &str) -> Option<Self> {
808        match value {
809            "FirmwareUpdated" => Some(Self::FirmwareUpdated),
810            "FailedToAuthenticateAtCsms" => Some(Self::FailedToAuthenticateAtCsms),
811            "CsmsFailedToAuthenticate" => Some(Self::CsmsFailedToAuthenticate),
812            "SettingSystemTime" => Some(Self::SettingSystemTime),
813            "StartupOfTheDevice" => Some(Self::StartupOfTheDevice),
814            "ResetOrReboot" => Some(Self::ResetOrReboot),
815            "SecurityLogWasCleared" => Some(Self::SecurityLogWasCleared),
816            "ReconfigurationOfSecurityParameters" => {
817                Some(Self::ReconfigurationOfSecurityParameters)
818            }
819            "MemoryExhaustion" => Some(Self::MemoryExhaustion),
820            "InvalidMessages" => Some(Self::InvalidMessages),
821            "AttemptedReplayAttacks" => Some(Self::AttemptedReplayAttacks),
822            "TamperDetectionActivated" => Some(Self::TamperDetectionActivated),
823            "InvalidFirmwareSignature" => Some(Self::InvalidFirmwareSignature),
824            "InvalidFirmwareSigningCertificate" => {
825                Some(Self::InvalidFirmwareSigningCertificate)
826            }
827            "InvalidCsmsCertificate" => Some(Self::InvalidCsmsCertificate),
828            "InvalidChargePointCertificate" => Some(Self::InvalidChargePointCertificate),
829            "InvalidTLSVersion" => Some(Self::InvalidTLSVersion),
830            "InvalidTLSCipherSuite" => Some(Self::InvalidTLSCipherSuite),
831            "MaintenanceLoginAccepted" => Some(Self::MaintenanceLoginAccepted),
832            "MaintenanceLoginFailed" => Some(Self::MaintenanceLoginFailed),
833            _ => None,
834        }
835    }
836    /// Whether the Security Whitepaper marks this event critical, meaning it must be reported to the Central System even when not explicitly monitored.
837    pub const fn is_critical(&self) -> bool {
838        match self {
839            Self::FirmwareUpdated => true,
840            Self::FailedToAuthenticateAtCsms => false,
841            Self::CsmsFailedToAuthenticate => false,
842            Self::SettingSystemTime => true,
843            Self::StartupOfTheDevice => true,
844            Self::ResetOrReboot => true,
845            Self::SecurityLogWasCleared => true,
846            Self::ReconfigurationOfSecurityParameters => false,
847            Self::MemoryExhaustion => true,
848            Self::InvalidMessages => false,
849            Self::AttemptedReplayAttacks => false,
850            Self::TamperDetectionActivated => true,
851            Self::InvalidFirmwareSignature => true,
852            Self::InvalidFirmwareSigningCertificate => true,
853            Self::InvalidCsmsCertificate => true,
854            Self::InvalidChargePointCertificate => true,
855            Self::InvalidTLSVersion => true,
856            Self::InvalidTLSCipherSuite => true,
857            Self::MaintenanceLoginAccepted => true,
858            Self::MaintenanceLoginFailed => true,
859        }
860    }
861}
862impl core::fmt::Display for SecurityEvent {
863    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
864        f.write_str(self.as_str())
865    }
866}
867impl core::str::FromStr for SecurityEvent {
868    type Err = UnknownValue;
869    fn from_str(value: &str) -> Result<Self, Self::Err> {
870        Self::from_wire(value).ok_or(UnknownValue)
871    }
872}