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