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#[serde(rename_all = "camelCase")]
33pub struct EnergyAmount {
34 #[serde(flatten)]
36 pub meta: Bo4eMeta,
37
38 #[serde(skip_serializing_if = "Option::is_none")]
40 pub energy_amount_id: Option<String>,
41
42 #[serde(skip_serializing_if = "Option::is_none")]
44 pub division: Option<Division>,
45
46 #[serde(skip_serializing_if = "Option::is_none")]
48 pub energy_direction: Option<EnergyDirection>,
49
50 #[serde(skip_serializing_if = "Option::is_none")]
52 pub measurement_type: Option<MeasurementType>,
53
54 #[serde(skip_serializing_if = "Option::is_none")]
56 pub validity_period: Option<TimePeriod>,
57
58 #[serde(default, skip_serializing_if = "Vec::is_empty")]
60 pub measured_values: Vec<MeasuredValue>,
61
62 #[serde(skip_serializing_if = "Option::is_none")]
64 pub market_location_id: Option<String>,
65
66 #[serde(skip_serializing_if = "Option::is_none")]
68 pub metering_location_id: Option<String>,
69
70 #[serde(skip_serializing_if = "Option::is_none")]
72 pub obis_code: Option<String>,
73
74 #[serde(skip_serializing_if = "Option::is_none")]
76 pub total_energy: Option<f64>,
77}
78
79impl Bo4eObject for EnergyAmount {
80 fn type_name_german() -> &'static str {
81 "Energiemenge"
82 }
83
84 fn type_name_english() -> &'static str {
85 "EnergyAmount"
86 }
87
88 fn meta(&self) -> &Bo4eMeta {
89 &self.meta
90 }
91
92 fn meta_mut(&mut self) -> &mut Bo4eMeta {
93 &mut self.meta
94 }
95}
96
97#[cfg(test)]
98mod tests {
99 use super::*;
100
101 #[test]
102 fn test_energy_amount_creation() {
103 let energy = EnergyAmount {
104 energy_amount_id: Some("EA001".to_string()),
105 division: Some(Division::Electricity),
106 energy_direction: Some(EnergyDirection::FeedOut),
107 ..Default::default()
108 };
109
110 assert_eq!(energy.energy_amount_id, Some("EA001".to_string()));
111 }
112
113 #[test]
114 fn test_serialize() {
115 let energy = EnergyAmount {
116 meta: Bo4eMeta::with_type("Energiemenge"),
117 energy_amount_id: Some("EA001".to_string()),
118 ..Default::default()
119 };
120
121 let json = serde_json::to_string(&energy).unwrap();
122 assert!(json.contains(r#""_typ":"Energiemenge""#));
123 }
124
125 #[test]
126 fn test_roundtrip() {
127 let energy = EnergyAmount {
128 meta: Bo4eMeta::with_type("Energiemenge"),
129 energy_amount_id: Some("EA001".to_string()),
130 division: Some(Division::Electricity),
131 energy_direction: Some(EnergyDirection::FeedOut),
132 total_energy: Some(1234.56),
133 obis_code: Some("1-0:1.8.0".to_string()),
134 ..Default::default()
135 };
136
137 let json = serde_json::to_string(&energy).unwrap();
138 let parsed: EnergyAmount = serde_json::from_str(&json).unwrap();
139 assert_eq!(energy, parsed);
140 }
141
142 #[test]
143 fn test_bo4e_object_impl() {
144 assert_eq!(EnergyAmount::type_name_german(), "Energiemenge");
145 assert_eq!(EnergyAmount::type_name_english(), "EnergyAmount");
146 }
147}