frequenz_microgrid_component_graph/
component_category.rs

1// License: MIT
2// Copyright © 2024 Frequenz Energy-as-a-Service GmbH
3
4//! This module defines the `ComponentCategory` enum, which represents the
5//! category of a component.
6
7use crate::ComponentGraphConfig;
8use crate::graph_traits::Node;
9use std::fmt::Display;
10
11/// Represents the type of an inverter.
12#[derive(Clone, Copy, Debug, PartialEq)]
13pub enum InverterType {
14    Unspecified,
15    Pv,
16    Battery,
17    Hybrid,
18}
19
20impl Display for InverterType {
21    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
22        match self {
23            InverterType::Unspecified => write!(f, "Unspecified"),
24            InverterType::Pv => write!(f, "Pv"),
25            InverterType::Battery => write!(f, "Battery"),
26            InverterType::Hybrid => write!(f, "Hybrid"),
27        }
28    }
29}
30
31/// Represents the type of a battery.
32#[derive(Clone, Copy, Debug, PartialEq)]
33pub enum BatteryType {
34    Unspecified,
35    LiIon,
36    NaIon,
37}
38
39impl Display for BatteryType {
40    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
41        match self {
42            BatteryType::Unspecified => write!(f, "Unspecified"),
43            BatteryType::LiIon => write!(f, "LiIon"),
44            BatteryType::NaIon => write!(f, "NaIon"),
45        }
46    }
47}
48
49/// Represents the type of an EV charger.
50#[derive(Clone, Copy, Debug, PartialEq)]
51pub enum EvChargerType {
52    Unspecified,
53    Ac,
54    Dc,
55    Hybrid,
56}
57
58impl Display for EvChargerType {
59    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
60        match self {
61            EvChargerType::Unspecified => write!(f, "Unspecified"),
62            EvChargerType::Ac => write!(f, "AC"),
63            EvChargerType::Dc => write!(f, "DC"),
64            EvChargerType::Hybrid => write!(f, "Hybrid"),
65        }
66    }
67}
68
69/// Represents the category of a component.
70///
71/// Values of the underlying generated `ComponentCategory` and `ComponentType` types
72/// need to be converted to this type, so that they can be used in the
73/// `ComponentGraph`.
74#[derive(Clone, Copy, Debug, PartialEq)]
75pub enum ComponentCategory {
76    Unspecified,
77    GridConnectionPoint,
78    Meter,
79    Inverter(InverterType),
80    Converter,
81    Battery(BatteryType),
82    EvCharger(EvChargerType),
83    Breaker,
84    Precharger,
85    Chp,
86    Electrolyzer,
87    PowerTransformer,
88    Hvac,
89    Plc,
90    CryptoMiner,
91    StaticTransferSwitch,
92    UninterruptiblePowerSupply,
93    CapacitorBank,
94    WindTurbine,
95}
96
97impl Display for ComponentCategory {
98    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
99        match self {
100            ComponentCategory::Unspecified => write!(f, "Unspecified"),
101            ComponentCategory::GridConnectionPoint => write!(f, "GridConnectionPoint"),
102            ComponentCategory::Meter => write!(f, "Meter"),
103            ComponentCategory::Battery(battery_type) => write!(f, "Battery({battery_type})"),
104            ComponentCategory::Inverter(inverter_type) => write!(f, "{inverter_type}Inverter"),
105            ComponentCategory::EvCharger(ev_charger_type) => {
106                write!(f, "EVCharger({ev_charger_type})")
107            }
108            ComponentCategory::Converter => write!(f, "Converter"),
109            ComponentCategory::CryptoMiner => write!(f, "CryptoMiner"),
110            ComponentCategory::Electrolyzer => write!(f, "Electrolyzer"),
111            ComponentCategory::Chp => write!(f, "CHP"),
112            ComponentCategory::Precharger => write!(f, "Precharger"),
113            ComponentCategory::Hvac => write!(f, "HVAC"),
114            ComponentCategory::Breaker => write!(f, "Breaker"),
115            ComponentCategory::PowerTransformer => write!(f, "PowerTransformer"),
116            ComponentCategory::Plc => write!(f, "PLC"),
117            ComponentCategory::StaticTransferSwitch => write!(f, "StaticTransferSwitch"),
118            ComponentCategory::UninterruptiblePowerSupply => {
119                write!(f, "UninterruptiblePowerSupply")
120            }
121            ComponentCategory::CapacitorBank => write!(f, "CapacitorBank"),
122            ComponentCategory::WindTurbine => write!(f, "WindTurbine"),
123        }
124    }
125}
126
127/// Predicates for checking the component category of a `Node`.
128pub(crate) trait CategoryPredicates: Node {
129    fn is_unspecified(&self) -> bool {
130        self.category() == ComponentCategory::Unspecified
131    }
132
133    fn is_grid(&self) -> bool {
134        self.category() == ComponentCategory::GridConnectionPoint
135    }
136
137    fn is_meter(&self) -> bool {
138        self.category() == ComponentCategory::Meter
139    }
140
141    fn is_battery(&self) -> bool {
142        matches!(self.category(), ComponentCategory::Battery(_))
143    }
144
145    fn is_inverter(&self) -> bool {
146        matches!(self.category(), ComponentCategory::Inverter(_))
147    }
148
149    fn is_battery_inverter(&self, config: &ComponentGraphConfig) -> bool {
150        match self.category() {
151            ComponentCategory::Inverter(InverterType::Battery) => true,
152            ComponentCategory::Inverter(InverterType::Unspecified) => {
153                config.allow_unspecified_inverters
154            }
155            _ => false,
156        }
157    }
158
159    fn is_pv_inverter(&self) -> bool {
160        self.category() == ComponentCategory::Inverter(InverterType::Pv)
161    }
162
163    fn is_hybrid_inverter(&self) -> bool {
164        self.category() == ComponentCategory::Inverter(InverterType::Hybrid)
165    }
166
167    fn is_unspecified_inverter(&self, config: &ComponentGraphConfig) -> bool {
168        match self.category() {
169            ComponentCategory::Inverter(InverterType::Unspecified) => {
170                !config.allow_unspecified_inverters
171            }
172            _ => false,
173        }
174    }
175
176    fn is_ev_charger(&self) -> bool {
177        matches!(self.category(), ComponentCategory::EvCharger(_))
178    }
179
180    fn is_chp(&self) -> bool {
181        self.category() == ComponentCategory::Chp
182    }
183
184    fn is_wind_turbine(&self) -> bool {
185        self.category() == ComponentCategory::WindTurbine
186    }
187}
188
189/// Implement the `CategoryPredicates` trait for all types that implement the
190/// `Node` trait.
191impl<T: Node> CategoryPredicates for T {}