@@ -120,6 +120,20 @@ def successors(self, component_id: int) -> set[Component]:
120120 KeyError: if the specified `component_id` is not in the graph
121121 """
122122
123+ @abstractmethod
124+ def is_grid_meter (self , component : Component ) -> bool :
125+ """Check if the specified component is a grid meter.
126+
127+ This is done by checking if the component is the only successor to the `Grid`
128+ component.
129+
130+ Args:
131+ component: component to check.
132+
133+ Returns:
134+ Whether the specified component is a grid meter.
135+ """
136+
123137 @abstractmethod
124138 def is_pv_inverter (self , component : Component ) -> bool :
125139 """Check if the specified component is a PV inverter.
@@ -567,6 +581,32 @@ def validate(self) -> None:
567581 self ._validate_intermediary_components ()
568582 self ._validate_leaf_components ()
569583
584+ def is_grid_meter (self , component : Component ) -> bool :
585+ """Check if the specified component is a grid meter.
586+
587+ This is done by checking if the component is the only successor to the `Grid`
588+ component.
589+
590+ Args:
591+ component: component to check.
592+
593+ Returns:
594+ Whether the specified component is a grid meter.
595+ """
596+ if component .category != ComponentCategory .METER :
597+ return False
598+
599+ predecessors = self .predecessors (component .component_id )
600+ if len (predecessors ) != 1 :
601+ return False
602+
603+ predecessor = next (iter (predecessors ))
604+ if predecessor .category != ComponentCategory .GRID :
605+ return False
606+
607+ grid_successors = self .successors (predecessor .component_id )
608+ return len (grid_successors ) == 1
609+
570610 def is_pv_inverter (self , component : Component ) -> bool :
571611 """Check if the specified component is a PV inverter.
572612
@@ -596,6 +636,7 @@ def is_pv_meter(self, component: Component) -> bool:
596636 successors = self .successors (component .component_id )
597637 return (
598638 component .category == ComponentCategory .METER
639+ and not self .is_grid_meter (component )
599640 and len (successors ) > 0
600641 and all (
601642 self .is_pv_inverter (successor )
@@ -643,6 +684,7 @@ def is_ev_charger_meter(self, component: Component) -> bool:
643684 successors = self .successors (component .component_id )
644685 return (
645686 component .category == ComponentCategory .METER
687+ and not self .is_grid_meter (component )
646688 and len (successors ) > 0
647689 and all (self .is_ev_charger (successor ) for successor in successors )
648690 )
@@ -690,6 +732,7 @@ def is_battery_meter(self, component: Component) -> bool:
690732 successors = self .successors (component .component_id )
691733 return (
692734 component .category == ComponentCategory .METER
735+ and not self .is_grid_meter (component )
693736 and len (successors ) > 0
694737 and all (self .is_battery_inverter (successor ) for successor in successors )
695738 )
@@ -734,6 +777,7 @@ def is_chp_meter(self, component: Component) -> bool:
734777 successors = self .successors (component .component_id )
735778 return (
736779 component .category == ComponentCategory .METER
780+ and not self .is_grid_meter (component )
737781 and len (successors ) > 0
738782 and all (self .is_chp (successor ) for successor in successors )
739783 )
0 commit comments