ocpi_kit/v2_2_1/hub_client_info.rs
1//! The *Hub Client Info* module of OCPI 2.2.1, as a delta from
2//! [`v2_3_0::hub_client_info`](crate::v2_3_0::hub_client_info).
3//!
4//! Only [`ClientInfo`] is redefined, because its `role` is the 2.2.1
5//! [`Role`], which still has `HUB`.
6//!
7//! **Spec erratum.** The Sender GET endpoint structure in
8//! §mod_hub_client_info of both 2.2.1 and 2.3.0 is written as `{locations_endpoint_url}?…`,
9//! copy-pasted from the Locations module, and the Receiver PUT example uses the path
10//! `/ocpi/cpo/2.0/clientinfo/…` — the wrong version and the wrong module identifier. The
11//! endpoint URL to use is the one discovered for `hubclientinfo`; examples are not normative.
12//!
13//! Spec: 2.2.1 §mod_hub_client_info_module
14
15use serde::{Deserialize, Serialize};
16
17use crate::types::validate_fields;
18use crate::types::{CountryCode, DateTime, Extensions, PartyId, PartyRef, Validate, Validator};
19
20use super::types::Role;
21
22// Wire-identical to OCPI 2.3.0.
23pub use crate::v2_3_0::hub_client_info::ConnectionStatus;
24
25/// The connection status of one party at a hub, in OCPI 2.2.1.
26///
27/// Spec: 2.2.1 §mod_hub_client_info_hub_client_info_object
28#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
29#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
30pub struct ClientInfo {
31 /// CPO or eMSP ID of this party, as used in the credentials exchange.
32 pub party_id: PartyId,
33 /// Country code of the country this party is operating in.
34 pub country_code: CountryCode,
35 /// The role of the connected party.
36 pub role: Role,
37 /// Status of the connection to the party.
38 pub status: ConnectionStatus,
39 /// Timestamp when this ClientInfo object was last updated.
40 pub last_updated: DateTime,
41 /// Undocumented JSON fields, preserved verbatim.
42 #[serde(flatten, default, skip_serializing_if = "Extensions::is_empty")]
43 pub extensions: Extensions,
44}
45
46impl ClientInfo {
47 /// Creates a client info entry.
48 #[must_use]
49 pub fn new(party: PartyRef, role: Role, status: ConnectionStatus, last_updated: DateTime) -> Self {
50 Self {
51 party_id: party.party_id,
52 country_code: party.country_code,
53 role,
54 status,
55 last_updated,
56 extensions: Extensions::new(),
57 }
58 }
59
60 /// The party this entry is about.
61 #[must_use]
62 pub fn party(&self) -> PartyRef {
63 PartyRef { country_code: self.country_code.clone(), party_id: self.party_id.clone() }
64 }
65
66 /// Whether messages can currently be delivered to this party.
67 #[must_use]
68 pub fn is_reachable(&self) -> bool {
69 self.status == ConnectionStatus::Connected
70 }
71}
72
73impl Validate for ClientInfo {
74 fn validate_in(&self, v: &mut Validator) {
75 validate_fields!(self, v, party_id, country_code, role, status, last_updated);
76 }
77}