bo4e_core/bo/
energy_amount.rs1use serde::{Deserialize, Serialize};
6
7use crate::com::{MeasuredValue, TimePeriod};
8use crate::enums::{Division, EnergyDirection, MeasurementType};
9use crate::traits::{Bo4eMeta, Bo4eObject};
10
11#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
32#[cfg_attr(feature = "json-schema", derive(schemars::JsonSchema))]
33#[cfg_attr(feature = "json-schema", schemars(rename = "Energiemenge"))]
34#[serde(rename_all = "camelCase")]
35pub struct EnergyAmount {
36 #[serde(flatten)]
38 pub meta: Bo4eMeta,
39
40 #[serde(skip_serializing_if = "Option::is_none")]
42 #[cfg_attr(feature = "json-schema", schemars(rename = "energiemengeId"))]
43 pub energy_amount_id: Option<String>,
44
45 #[serde(skip_serializing_if = "Option::is_none")]
47 #[cfg_attr(feature = "json-schema", schemars(rename = "sparte"))]
48 pub division: Option<Division>,
49
50 #[serde(skip_serializing_if = "Option::is_none")]
52 #[cfg_attr(feature = "json-schema", schemars(rename = "energierichtung"))]
53 pub energy_direction: Option<EnergyDirection>,
54
55 #[serde(skip_serializing_if = "Option::is_none")]
57 #[cfg_attr(feature = "json-schema", schemars(rename = "messart"))]
58 pub measurement_type: Option<MeasurementType>,
59
60 #[serde(skip_serializing_if = "Option::is_none")]
62 #[cfg_attr(feature = "json-schema", schemars(rename = "gueltigkeitszeitraum"))]
63 pub validity_period: Option<TimePeriod>,
64
65 #[serde(default, skip_serializing_if = "Vec::is_empty")]
67 #[cfg_attr(feature = "json-schema", schemars(rename = "messwerte"))]
68 pub measured_values: Vec<MeasuredValue>,
69
70 #[serde(skip_serializing_if = "Option::is_none")]
72 #[cfg_attr(feature = "json-schema", schemars(rename = "marktlokationsId"))]
73 pub market_location_id: Option<String>,
74
75 #[serde(skip_serializing_if = "Option::is_none")]
77 #[cfg_attr(feature = "json-schema", schemars(rename = "messlokationsId"))]
78 pub metering_location_id: Option<String>,
79
80 #[serde(skip_serializing_if = "Option::is_none")]
82 #[cfg_attr(feature = "json-schema", schemars(rename = "obisKennzahl"))]
83 pub obis_code: Option<String>,
84
85 #[serde(skip_serializing_if = "Option::is_none")]
87 #[cfg_attr(feature = "json-schema", schemars(rename = "gesamtenergie"))]
88 pub total_energy: Option<f64>,
89}
90
91impl Bo4eObject for EnergyAmount {
92 fn type_name_german() -> &'static str {
93 "Energiemenge"
94 }
95
96 fn type_name_english() -> &'static str {
97 "EnergyAmount"
98 }
99
100 fn meta(&self) -> &Bo4eMeta {
101 &self.meta
102 }
103
104 fn meta_mut(&mut self) -> &mut Bo4eMeta {
105 &mut self.meta
106 }
107}
108
109#[cfg(test)]
110mod tests {
111 use super::*;
112
113 #[test]
114 fn test_energy_amount_creation() {
115 let energy = EnergyAmount {
116 energy_amount_id: Some("EA001".to_string()),
117 division: Some(Division::Electricity),
118 energy_direction: Some(EnergyDirection::FeedOut),
119 ..Default::default()
120 };
121
122 assert_eq!(energy.energy_amount_id, Some("EA001".to_string()));
123 }
124
125 #[test]
126 fn test_serialize() {
127 let energy = EnergyAmount {
128 meta: Bo4eMeta::with_type("Energiemenge"),
129 energy_amount_id: Some("EA001".to_string()),
130 ..Default::default()
131 };
132
133 let json = serde_json::to_string(&energy).unwrap();
134 assert!(json.contains(r#""_typ":"Energiemenge""#));
135 }
136
137 #[test]
138 fn test_roundtrip() {
139 let energy = EnergyAmount {
140 meta: Bo4eMeta::with_type("Energiemenge"),
141 energy_amount_id: Some("EA001".to_string()),
142 division: Some(Division::Electricity),
143 energy_direction: Some(EnergyDirection::FeedOut),
144 total_energy: Some(1234.56),
145 obis_code: Some("1-0:1.8.0".to_string()),
146 ..Default::default()
147 };
148
149 let json = serde_json::to_string(&energy).unwrap();
150 let parsed: EnergyAmount = serde_json::from_str(&json).unwrap();
151 assert_eq!(energy, parsed);
152 }
153
154 #[test]
155 fn test_bo4e_object_impl() {
156 assert_eq!(EnergyAmount::type_name_german(), "Energiemenge");
157 assert_eq!(EnergyAmount::type_name_english(), "EnergyAmount");
158 }
159}