Skip to main content

energy_api/
lib.rs

1//! # energy-api
2//!
3//! Rust client and server bindings for the German energy market API-Webdienste
4//! (MaKo — Marktkommunikation).
5//!
6//! ## Module layout
7//!
8//! ```text
9//! energy_api
10//! ├── models/       OpenAPI/AsyncAPI types shared by all APIs
11//! ├── transport/    HTTP + mTLS builder, JWS sign/verify
12//! ├── directory/    Verzeichnisdienst — REST client, WebSocket client, server
13//! ├── client/       Electricity API clients  (feature = "client")
14//! │   ├── control_measures   NB/LF and MSB send calls
15//! │   └── malo_ident         LF and NB callback calls
16//! └── server/       Electricity API servers  (feature = "server")
17//!     ├── control_measures   MSB and NB/LF receive handlers + axum router
18//!     ├── malo_ident         NB and LF receive handlers + axum router
19//!     └── wim_order          MSB receive handler (iMS Anmeldung) + NB callbacks
20//! ```
21//!
22//! ## Feature flags
23//!
24//! | Feature     | Enables                                                  |
25//! |-------------|----------------------------------------------------------|
26//! | `client`    | HTTP clients for all APIs (reqwest + rustls)             |
27//! | `server`    | Axum router factories for server implementations         |
28//! | `websocket` | WebSocket subscription client (tokio-tungstenite)        |
29//! | `crypto`    | JWS ECDSA-SHA256 sign/verify for directory records (p256)|
30//!
31//! ## Quick start
32//!
33//! ### Look up an endpoint via the directory
34//!
35//! ```no_run
36//! # #[cfg(feature = "client")]
37//! # async fn example() -> Result<(), energy_api::Error> {
38//! use energy_api::directory::DirectoryServiceClient;
39//! use url::Url;
40//!
41//! let base = Url::parse("https://verzeichnisdienst.example.de/")?;
42//! let client = DirectoryServiceClient::new_insecure(base)?;
43//! let (record, _cert, _sig) = client
44//!     .get_record("1234567890123", "controlMeasuresV1", 1)
45//!     .await?;
46//! println!("{}", record.url);
47//! # Ok(())
48//! # }
49//! ```
50//!
51//! ### Send a grid control command
52//!
53//! ```no_run
54//! # #[cfg(feature = "client")]
55//! # async fn example() -> Result<(), energy_api::Error> {
56//! use energy_api::client::ControlMeasuresClient;
57//! use energy_api::models::electricity::{
58//!     CommandControl, LocationId, NeloId, MaximumPowerValue,
59//! };
60//! use url::Url;
61//! use uuid::Uuid;
62//!
63//! let client = ControlMeasuresClient::new(
64//!     Url::parse("https://msb.example.de/")?,
65//!     reqwest::Client::new(),
66//! );
67//! client.send_konfiguration(
68//!     Uuid::new_v4(),
69//!     "2025-06-01T10:00:00.000Z",
70//!     &LocationId::NetworkLocation(NeloId("E1234848431".into())),
71//!     &CommandControl {
72//!         maximum_power_value: MaximumPowerValue("10.5".into()),
73//!         execution_time_from: "2025-06-01T10:00:00Z".into(),
74//!         execution_time_until: None,
75//!     },
76//!     None,
77//! ).await?;
78//! # Ok(())
79//! # }
80//! ```
81
82#![allow(clippy::too_many_arguments)]
83#![allow(clippy::large_enum_variant)]
84
85pub mod directory;
86pub mod error;
87pub mod models;
88pub mod spec_version;
89pub mod transport;
90
91#[cfg(feature = "client")]
92pub mod client;
93
94#[cfg(feature = "server")]
95pub mod server;
96
97pub use error::Error;