bo4e_core/com/
consumption.rs1use chrono::{DateTime, Utc};
4use serde::{Deserialize, Serialize};
5
6use crate::enums::{MeasuredValueStatus, Unit};
7use crate::traits::{Bo4eMeta, Bo4eObject};
8
9#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
27#[cfg_attr(feature = "json-schema", derive(schemars::JsonSchema))]
28#[cfg_attr(feature = "json-schema", schemars(rename = "Verbrauch"))]
29#[serde(rename_all = "camelCase")]
30pub struct Consumption {
31 #[serde(flatten)]
33 pub meta: Bo4eMeta,
34
35 #[serde(skip_serializing_if = "Option::is_none")]
37 #[cfg_attr(feature = "json-schema", schemars(rename = "wert"))]
38 pub value: Option<f64>,
39
40 #[serde(skip_serializing_if = "Option::is_none")]
42 #[cfg_attr(feature = "json-schema", schemars(rename = "einheit"))]
43 pub unit: Option<Unit>,
44
45 #[serde(skip_serializing_if = "Option::is_none")]
47 #[cfg_attr(feature = "json-schema", schemars(rename = "startdatum"))]
48 pub start_date: Option<DateTime<Utc>>,
49
50 #[serde(skip_serializing_if = "Option::is_none")]
52 #[cfg_attr(feature = "json-schema", schemars(rename = "enddatum"))]
53 pub end_date: Option<DateTime<Utc>>,
54
55 #[serde(skip_serializing_if = "Option::is_none")]
57 #[cfg_attr(feature = "json-schema", schemars(rename = "obisKennzahl"))]
58 pub obis_code: Option<String>,
59
60 #[serde(skip_serializing_if = "Option::is_none")]
62 #[cfg_attr(feature = "json-schema", schemars(rename = "messwertstatus"))]
63 pub measured_value_status: Option<MeasuredValueStatus>,
64}
65
66impl Bo4eObject for Consumption {
67 fn type_name_german() -> &'static str {
68 "Verbrauch"
69 }
70
71 fn type_name_english() -> &'static str {
72 "Consumption"
73 }
74
75 fn meta(&self) -> &Bo4eMeta {
76 &self.meta
77 }
78
79 fn meta_mut(&mut self) -> &mut Bo4eMeta {
80 &mut self.meta
81 }
82}
83
84#[cfg(test)]
85mod tests {
86 use super::*;
87
88 #[test]
89 fn test_electricity_consumption() {
90 let consumption = Consumption {
91 value: Some(3660.0),
92 unit: Some(Unit::KilowattHour),
93 obis_code: Some("1-1:1.8.0".to_string()),
94 measured_value_status: Some(MeasuredValueStatus::Read),
95 ..Default::default()
96 };
97
98 assert_eq!(consumption.value, Some(3660.0));
99 assert_eq!(consumption.unit, Some(Unit::KilowattHour));
100 }
101
102 #[test]
103 fn test_gas_consumption() {
104 let consumption = Consumption {
105 value: Some(1250.0),
106 unit: Some(Unit::CubicMeter),
107 obis_code: Some("7-0:3.0.0".to_string()),
108 ..Default::default()
109 };
110
111 assert_eq!(consumption.unit, Some(Unit::CubicMeter));
112 }
113
114 #[test]
115 fn test_default() {
116 let consumption = Consumption::default();
117 assert!(consumption.value.is_none());
118 assert!(consumption.unit.is_none());
119 assert!(consumption.obis_code.is_none());
120 }
121
122 #[test]
123 fn test_serialize() {
124 let consumption = Consumption {
125 value: Some(1500.0),
126 unit: Some(Unit::KilowattHour),
127 obis_code: Some("1-1:1.8.1".to_string()),
128 ..Default::default()
129 };
130
131 let json = serde_json::to_string(&consumption).unwrap();
132 assert!(json.contains(r#""value":1500"#));
133 assert!(json.contains(r#""obisCode":"1-1:1.8.1""#));
134 }
135
136 #[test]
137 fn test_roundtrip() {
138 let consumption = Consumption {
139 value: Some(4500.5),
140 unit: Some(Unit::KilowattHour),
141 start_date: Some(
142 DateTime::parse_from_rfc3339("2024-01-01T00:00:00Z")
143 .unwrap()
144 .into(),
145 ),
146 end_date: Some(
147 DateTime::parse_from_rfc3339("2024-12-31T23:59:59Z")
148 .unwrap()
149 .into(),
150 ),
151 obis_code: Some("1-1:1.8.0".to_string()),
152 measured_value_status: Some(MeasuredValueStatus::Read),
153 ..Default::default()
154 };
155
156 let json = serde_json::to_string(&consumption).unwrap();
157 let parsed: Consumption = serde_json::from_str(&json).unwrap();
158 assert_eq!(consumption, parsed);
159 }
160
161 #[test]
162 fn test_bo4e_object_impl() {
163 assert_eq!(Consumption::type_name_german(), "Verbrauch");
164 assert_eq!(Consumption::type_name_english(), "Consumption");
165 }
166}