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
//! # energy-api
//!
//! Rust client and server bindings for the German energy market API-Webdienste
//! (MaKo — Marktkommunikation).
//!
//! ## Module layout
//!
//! ```text
//! energy_api
//! ├── models/ OpenAPI/AsyncAPI types shared by all APIs
//! ├── transport/ HTTP + mTLS builder, JWS sign/verify
//! ├── directory/ Verzeichnisdienst — REST client, WebSocket client, server
//! ├── client/ Electricity API clients (feature = "client")
//! │ ├── control_measures NB/LF and MSB send calls
//! │ └── malo_ident LF and NB callback calls
//! └── server/ Electricity API servers (feature = "server")
//! ├── control_measures MSB and NB/LF receive handlers + axum router
//! └── malo_ident NB and LF receive handlers + axum router
//! ```
//!
//! ## Feature flags
//!
//! | Feature | Enables |
//! |-------------|----------------------------------------------------------|
//! | `client` | HTTP clients for all APIs (reqwest + rustls) |
//! | `server` | Axum router factories for server implementations |
//! | `websocket` | WebSocket subscription client (tokio-tungstenite) |
//! | `crypto` | JWS ECDSA-SHA256 sign/verify for directory records (p256)|
//!
//! ## Quick start
//!
//! ### Look up an endpoint via the directory
//!
//! ```no_run
//! # #[cfg(feature = "client")]
//! # async fn example() -> Result<(), energy_api::Error> {
//! use energy_api::directory::DirectoryServiceClient;
//! use url::Url;
//!
//! let base = Url::parse("https://verzeichnisdienst.example.de/")?;
//! let client = DirectoryServiceClient::new_insecure(base)?;
//! let (record, _cert, _sig) = client
//! .get_record("1234567890123", "controlMeasuresV1", 1)
//! .await?;
//! println!("{}", record.url);
//! # Ok(())
//! # }
//! ```
//!
//! ### Send a grid control command
//!
//! ```no_run
//! # #[cfg(feature = "client")]
//! # async fn example() -> Result<(), energy_api::Error> {
//! use energy_api::client::ControlMeasuresClient;
//! use energy_api::models::electricity::{
//! CommandControl, LocationId, NeloId, MaximumPowerValue,
//! };
//! use url::Url;
//! use uuid::Uuid;
//!
//! let client = ControlMeasuresClient::new(
//! Url::parse("https://msb.example.de/")?,
//! reqwest::Client::new(),
//! );
//! client.send_konfiguration(
//! Uuid::new_v4(),
//! "2025-06-01T10:00:00.000Z",
//! &LocationId::NetworkLocation(NeloId("E1234848431".into())),
//! &CommandControl {
//! maximum_power_value: MaximumPowerValue("10.5".into()),
//! execution_time_from: "2025-06-01T10:00:00Z".into(),
//! execution_time_until: None,
//! },
//! None,
//! ).await?;
//! # Ok(())
//! # }
//! ```
pub use Error;