Skip to main content

energy_api/
lib.rs

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