frequenz_microgrid_component_graph/graph_traits.rs
1// License: MIT
2// Copyright © 2024 Frequenz Energy-as-a-Service GmbH
3
4//! This module contains the traits that need to be implemented by the types
5//! that represent a node and an edge.
6
7use crate::component_category::ComponentCategory;
8
9/**
10This trait needs to be implemented by the type that represents a node.
11
12Read more about why this is necessary [here][crate#the-node-and-edge-traits].
13
14<details>
15<summary>Example implementation for microgrid API v0.17:</summary>
16
17```ignore
18impl frequenz_microgrid_component_graph::Node for common::v1::microgrid::components::Component {
19 fn component_id(&self) -> u64 {
20 self.id as u64
21 }
22
23 fn category(&self) -> frequenz_microgrid_component_graph::ComponentCategory {
24 use common::v1::microgrid::components as pb;
25 use frequenz_microgrid_component_graph as gr;
26
27 let category = pb::ComponentCategory::try_from(self.category).unwrap_or_else(|e| {
28 error!("Error converting component category: {}", e);
29 pb::ComponentCategory::Unspecified
30 });
31
32 match category {
33 pb::ComponentCategory::Unspecified => gr::ComponentCategory::Unspecified,
34 pb::ComponentCategory::Grid => gr::ComponentCategory::Grid,
35 pb::ComponentCategory::Meter => gr::ComponentCategory::Meter,
36 pb::ComponentCategory::Inverter => {
37 gr::ComponentCategory::Inverter(match self.category_type {
38 Some(pb::ComponentCategoryMetadataVariant { metadata }) => match metadata {
39 Some(pb::component_category_metadata_variant::Metadata::Inverter(
40 inverter,
41 )) => {
42 match pb::InverterType::try_from(inverter.r#type).unwrap_or_else(|e| {
43 error!("Error converting inverter type: {}", e);
44 pb::InverterType::Unspecified
45 }) {
46 pb::InverterType::Solar => gr::InverterType::Solar,
47 pb::InverterType::Battery => gr::InverterType::Battery,
48 pb::InverterType::Hybrid => gr::InverterType::Hybrid,
49 pb::InverterType::Unspecified => gr::InverterType::Unspecified,
50 }
51 }
52 Some(_) => {
53 warn!("Unknown metadata variant for inverter: {:?}", metadata);
54 gr::InverterType::Unspecified
55 }
56 None => gr::InverterType::Unspecified,
57 },
58 _ => gr::InverterType::Unspecified,
59 })
60 }
61 pb::ComponentCategory::Converter => gr::ComponentCategory::Converter,
62 pb::ComponentCategory::Battery => {
63 gr::ComponentCategory::Battery(match self.category_type {
64 Some(pb::ComponentCategoryMetadataVariant { metadata }) => match metadata {
65 Some(pb::component_category_metadata_variant::Metadata::Battery(
66 battery,
67 )) => match pb::BatteryType::try_from(battery.r#type).unwrap_or_else(|e| {
68 error!("Error converting battery type: {}", e);
69 pb::BatteryType::Unspecified
70 }) {
71 pb::BatteryType::LiIon => gr::BatteryType::LiIon,
72 pb::BatteryType::NaIon => gr::BatteryType::NaIon,
73 pb::BatteryType::Unspecified => gr::BatteryType::Unspecified,
74 },
75 Some(_) => {
76 warn!("Unknown metadata variant for battery: {:?}", metadata);
77 gr::BatteryType::Unspecified
78 }
79 None => gr::BatteryType::Unspecified,
80 },
81 _ => gr::BatteryType::Unspecified,
82 })
83 }
84 pb::ComponentCategory::EvCharger => {
85 gr::ComponentCategory::EvCharger(match self.category_type {
86 Some(pb::ComponentCategoryMetadataVariant { metadata }) => match metadata {
87 Some(pb::component_category_metadata_variant::Metadata::EvCharger(
88 ev_charger,
89 )) => match pb::EvChargerType::try_from(ev_charger.r#type).unwrap_or_else(
90 |e| {
91 error!("Error converting ev charger type: {}", e);
92 pb::EvChargerType::Unspecified
93 },
94 ) {
95 pb::EvChargerType::Ac => gr::EvChargerType::Ac,
96 pb::EvChargerType::Dc => gr::EvChargerType::Dc,
97 pb::EvChargerType::Hybrid => gr::EvChargerType::Hybrid,
98 pb::EvChargerType::Unspecified => gr::EvChargerType::Unspecified,
99 },
100 Some(_) => {
101 warn!("Unknown metadata variant for ev charger: {:?}", metadata);
102 gr::EvChargerType::Unspecified
103 }
104 None => gr::EvChargerType::Unspecified,
105 },
106 _ => gr::EvChargerType::Unspecified,
107 })
108 }
109 pb::ComponentCategory::CryptoMiner => gr::ComponentCategory::CryptoMiner,
110 pb::ComponentCategory::Electrolyzer => gr::ComponentCategory::Electrolyzer,
111 pb::ComponentCategory::Chp => gr::ComponentCategory::Chp,
112 pb::ComponentCategory::Relay => gr::ComponentCategory::Relay,
113 pb::ComponentCategory::Precharger => gr::ComponentCategory::Precharger,
114 pb::ComponentCategory::Fuse => gr::ComponentCategory::Fuse,
115 pb::ComponentCategory::VoltageTransformer => gr::ComponentCategory::VoltageTransformer,
116 pb::ComponentCategory::Hvac => gr::ComponentCategory::Hvac,
117 }
118 }
119}
120```
121
122</details>
123*/
124pub trait Node {
125 /// Returns the component id of the component.
126 fn component_id(&self) -> u64;
127 /// Returns the category of the category.
128 fn category(&self) -> ComponentCategory;
129}
130
131/**
132This trait needs to be implemented by the type that represents a connection.
133
134Read more about why this is necessary [here][crate#the-node-and-edge-traits].
135
136<details>
137<summary>Example implementation for microgrid API v0.17:</summary>
138
139```ignore
140impl frequenz_microgrid_component_graph::Edge
141 for common::v1::microgrid::components::ComponentConnection
142{
143 fn source(&self) -> u64 {
144 self.source_component_id
145 }
146
147 fn destination(&self) -> u64 {
148 self.destination_component_id
149 }
150}
151```
152
153</details>
154*/
155pub trait Edge {
156 /// Returns the source component id of the connection.
157 fn source(&self) -> u64;
158 /// Returns the destination component id of the connection.
159 fn destination(&self) -> u64;
160}