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}