From 9cb1635bd570263bf7f51f506948999e827f10af Mon Sep 17 00:00:00 2001 From: AAndersn Date: Tue, 17 Jan 2023 15:32:52 -0800 Subject: [PATCH] library build --- pyproject.toml | 2 +- topology_processor/__init__.py | 38 +++++++++++++- topology_processor/blazegraph.py | 19 +++++++ topology_processor/distributedtopology.py | 52 ++++++++++--------- topology_processor/networkmodel.py | 2 +- topology_processor/topo_meas_queries.py | 27 +++++----- topology_processor/topo_tester.py | 6 +-- ...pologyprocessor.py => topologyprocessor.py | 7 +-- .../topologyservice.py => topologyservice.py | 6 +-- 9 files changed, 110 insertions(+), 49 deletions(-) create mode 100644 topology_processor/blazegraph.py rename topology_processor/topologyprocessor.py => topologyprocessor.py (97%) rename topology_processor/topologyservice.py => topologyservice.py (97%) diff --git a/pyproject.toml b/pyproject.toml index a8ffeaa..e8d7ef8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "gridappsd-topology-processor" -version = "0.1.0" +version = "0.2.0" description = "" authors = ["C. Allwardt <3979063+craig8@users.noreply.github.com>"] packages = [ diff --git a/topology_processor/__init__.py b/topology_processor/__init__.py index 8977518..1c6b41f 100644 --- a/topology_processor/__init__.py +++ b/topology_processor/__init__.py @@ -43,8 +43,44 @@ main GridAPPSD executable. """ -from . topologyprocessor import TopologyProcessor from . distributedtopology import DistributedTopology from . networkmodel import NetworkModel from . topologydictionary import TopologyDictionary + +# @dataclass +# class Parameter: +# key: Any +# value: Any + + +# @dataclass +# class ConnectionParameters: +# parameters: List[Parameter] = field(default_factory=list) + + +# @dataclass +# class QueryResponse: +# response: Any + + +# @dataclass +# class ConnectionInterface: +# connection_params: ConnectionParameters + +# def connect(self): +# raise RuntimeError("Must have implemented connect in inherited class") + +# def disconnect(self): +# raise RuntimeError("Must have implemented disconnect in inherited class") + +# def load_attributes(self, obj: object): +# raise RuntimeError("Must have implemented load_attributes in inherited class") + +# def create_default_instances(self, feeder_mrid: str | Feeder, mrid_list: List[str]): +# raise RuntimeError("Must have implemented retrieve_instance from inherited class") + +# def execute(self, query: str) -> QueryResponse: +# raise RuntimeError("Must have implemented query in the inherited class") + + diff --git a/topology_processor/blazegraph.py b/topology_processor/blazegraph.py new file mode 100644 index 0000000..907a751 --- /dev/null +++ b/topology_processor/blazegraph.py @@ -0,0 +1,19 @@ +from SPARQLWrapper import SPARQLWrapper, JSON, POST +class BlazegraphConnection(ConnectionInterface): + sparql_obj: Optional[SPARQLWrapper] = None + + def connect(self): + if not self.sparql_obj: + url = self.connection_params.parameters[0].value + self.sparql_obj = SPARQLWrapper(url) + self.sparql_obj.setReturnFormat(JSON) + + def disconnect(self): + self.sparql_obj = None + + def execute(self, query_message: str) -> QueryResponse: + self.connect() + self.sparql_obj.setQuery(query_message) + self.sparql_obj.setMethod(POST) + query_output = self.sparql_obj.query().convert() + return query_output \ No newline at end of file diff --git a/topology_processor/distributedtopology.py b/topology_processor/distributedtopology.py index 99ad8f4..15906ec 100644 --- a/topology_processor/distributedtopology.py +++ b/topology_processor/distributedtopology.py @@ -1,6 +1,6 @@ import time, json -from topologydictionary import TopologyDictionary -from networkmodel import NetworkModel +from topology_processor.topologydictionary import TopologyDictionary +from topology_processor.networkmodel import NetworkModel class DistributedTopology(): @@ -41,13 +41,13 @@ def create_switch_areas(self, model_mrid): def create_output_message(self,Topology, MVTree, model_mrid): ConnNodeDict = Topology.ConnNodeDict # Initialize output message structure - DistAppStruct = {} - DistAppStruct['feeders'] = {} - DistAppStruct['feeders']['feeder_id'] = model_mrid - DistAppStruct['feeders']['addressable_equipment'] = [] - DistAppStruct['feeders']['unaddressable_equipment'] = [] - DistAppStruct['feeders']['connectivity_node'] = [] - DistAppStruct['feeders']['switch_areas'] = [] + self.DistAppStruct = {} + self.DistAppStruct['feeders'] = {} + self.DistAppStruct['feeders']['feeder_id'] = model_mrid + self.DistAppStruct['feeders']['addressable_equipment'] = [] + self.DistAppStruct['feeders']['unaddressable_equipment'] = [] + self.DistAppStruct['feeders']['connectivity_node'] = [] + self.DistAppStruct['feeders']['switch_areas'] = [] ProcessedNodes = [] # List to keep track of which nodes have been processed SwitchKeys = list(MVTree.keys()) # Get list of all switching devices from all CIM classes # Iterate through all switches @@ -79,6 +79,8 @@ def create_output_message(self,Topology, MVTree, model_mrid): SwitchArea['addressable_equipment'].extend(ConnNodeDict[node]['PowerElectronicsConnection']) SwitchArea['addressable_equipment'].extend(ConnNodeDict[node]['LinearShuntCompensator']) SwitchArea['addressable_equipment'].extend(ConnNodeDict[node]['RatioTapChanger']) + SwitchArea['addressable_equipment'].extend(ConnNodeDict[node]['EnergyConsumer']) + SwitchArea['addressable_equipment'].extend(ConnNodeDict[node]['House']) SwitchArea['addressable_equipment'].extend(ConnNodeDict[node]['BatteryUnit']) SwitchArea['addressable_equipment'].extend(ConnNodeDict[node]['PhotovoltaicUnit']) SwitchArea['unaddressable_equipment'].extend(ConnNodeDict[node]['ACLineSegment']) @@ -102,28 +104,30 @@ def create_output_message(self,Topology, MVTree, model_mrid): if SwitchArea['boundary_switches']: # Append switch area if not duplicate - DistAppStruct['feeders']['switch_areas'].append(dict(SwitchArea)) - DistAppStruct['feeders']['addressable_equipment'].extend(SwitchArea['boundary_switches']) - DistAppStruct['feeders']['unaddressable_equipment'].extend(SwitchArea['unaddressable_equipment']) + self.DistAppStruct['feeders']['switch_areas'].append(dict(SwitchArea)) + self.DistAppStruct['feeders']['addressable_equipment'].extend(SwitchArea['boundary_switches']) + self.DistAppStruct['feeders']['unaddressable_equipment'].extend(SwitchArea['unaddressable_equipment']) # Add missing nodes to feeder level (not in switch area or secondary area) AllNodes = list(ConnNodeDict.keys()) MissingNodes = list(set(AllNodes).difference(ProcessedNodes)) for i5 in range(len(MissingNodes)): node = MissingNodes[i5] - DistAppStruct['feeders']['addressable_equipment'].extend(ConnNodeDict[node]['SynchronousMachine']) - DistAppStruct['feeders']['addressable_equipment'].extend(ConnNodeDict[node]['PowerElectronicsConnection']) - DistAppStruct['feeders']['addressable_equipment'].extend(ConnNodeDict[node]['LinearShuntCompensator']) - DistAppStruct['feeders']['addressable_equipment'].extend(ConnNodeDict[node]['RatioTapChanger']) - DistAppStruct['feeders']['addressable_equipment'].extend(ConnNodeDict[node]['BatteryUnit']) - DistAppStruct['feeders']['addressable_equipment'].extend(ConnNodeDict[node]['PhotovoltaicUnit']) - DistAppStruct['feeders']['unaddressable_equipment'].extend(ConnNodeDict[node]['ACLineSegment']) - DistAppStruct['feeders']['unaddressable_equipment'].extend(ConnNodeDict[node]['PowerTransformer']) - DistAppStruct['feeders']['unaddressable_equipment'].extend(ConnNodeDict[node]['TransformerTank']) - DistAppStruct['feeders']['unaddressable_equipment'].extend(ConnNodeDict[node]['Measurement']) - DistAppStruct['feeders']['connectivity_node'].append(node) + self.DistAppStruct['feeders']['addressable_equipment'].extend(ConnNodeDict[node]['SynchronousMachine']) + self.DistAppStruct['feeders']['addressable_equipment'].extend(ConnNodeDict[node]['PowerElectronicsConnection']) + self.DistAppStruct['feeders']['addressable_equipment'].extend(ConnNodeDict[node]['LinearShuntCompensator']) + self.DistAppStruct['feeders']['addressable_equipment'].extend(ConnNodeDict[node]['RatioTapChanger']) + self.DistAppStruct['feeders']['addressable_equipment'].extend(ConnNodeDict[node]['EnergyConsumer']) + self.DistAppStruct['feeders']['addressable_equipment'].extend(ConnNodeDict[node]['House']) + self.DistAppStruct['feeders']['addressable_equipment'].extend(ConnNodeDict[node]['BatteryUnit']) + self.DistAppStruct['feeders']['addressable_equipment'].extend(ConnNodeDict[node]['PhotovoltaicUnit']) + self.DistAppStruct['feeders']['unaddressable_equipment'].extend(ConnNodeDict[node]['ACLineSegment']) + self.DistAppStruct['feeders']['unaddressable_equipment'].extend(ConnNodeDict[node]['PowerTransformer']) + self.DistAppStruct['feeders']['unaddressable_equipment'].extend(ConnNodeDict[node]['TransformerTank']) + self.DistAppStruct['feeders']['unaddressable_equipment'].extend(ConnNodeDict[node]['Measurement']) + self.DistAppStruct['feeders']['connectivity_node'].append(node) - return DistAppStruct + return self.DistAppStruct def create_dist_area(self, Topology, MVTree, Xfmrs, eqtype, SwitchArea): # Initialize secondary area dictionary diff --git a/topology_processor/networkmodel.py b/topology_processor/networkmodel.py index bf1247a..422698c 100644 --- a/topology_processor/networkmodel.py +++ b/topology_processor/networkmodel.py @@ -1,6 +1,6 @@ from gridappsd import GridAPPSD import time, json -import topo_meas_queries as queries +import topology_processor.topo_meas_queries as queries class NetworkModel(GridAPPSD): diff --git a/topology_processor/topo_meas_queries.py b/topology_processor/topo_meas_queries.py index 2797ef8..cd53625 100644 --- a/topology_processor/topo_meas_queries.py +++ b/topology_processor/topo_meas_queries.py @@ -1,6 +1,7 @@ # Custom SPARQL queries to obtain all equipment needed to build feeder topology -# Get all measurements points for all equipment from Blazegraph Database + + # Get all measurements points for all equipment from Blazegraph Database def get_all_measurements(gapps, model_mrid): QueryMeasurementMessage=""" # list all measurements, with buses and equipments - DistMeasurement @@ -32,13 +33,13 @@ def get_all_measurements(gapps, model_mrid): } ORDER BY ?cnid ?type """%model_mrid - + results = gapps.query_data(query = QueryMeasurementMessage, timeout = 60) MeasurementQuery = results['data']['results']['bindings'] return MeasurementQuery - - - + + + # Get all ConnectivityNode and TopologicalNode objects def get_all_nodes(gapps, model_mrid): QueryNodeMessage=""" @@ -56,7 +57,7 @@ def get_all_nodes(gapps, model_mrid): ?fdr c:IdentifiedObject.name ?feeder. ?trm c:Terminal.ConnectivityNode ?bus. ?trm c:Terminal.ConductingEquipment ?ce. - + OPTIONAL { ?ce c:ConductingEquipment.BaseVoltage ?bv. ?bv c:BaseVoltage.nominalVoltage ?nomu. @@ -116,7 +117,7 @@ def get_all_switches(gapps, model_mrid): results = gapps.query_data(query = QuerySwitchMessage, timeout = 60) SwitchQuery = results['data']['results']['bindings'] return SwitchQuery - + def get_all_transformers(gapps,model_mrid): QueryXfmrMessage=""" # list all the terminals connected to a TransformerEnd for CIMWriter @@ -192,7 +193,7 @@ def get_all_lines(gapps, model_mrid): OPTIONAL {?acp c:ACLineSegmentPhase.ACLineSegment ?s. ?acp c:ACLineSegmentPhase.phase ?phsraw. bind(strafter(str(?phsraw),"SinglePhaseKind.") as ?phs) } - + } ORDER BY ?name ?phs } GROUP BY ?name ?bus1 ?bus2 ?id ?tname1 ?term1 ?tname2 ?term2 ?node1 ?node2 ?tpnode1 ?tpnode2 @@ -261,7 +262,7 @@ def get_all_tapchangers(gapps, model_mrid): results = gapps.query_data(query = QueryTapMessage, timeout = 60) TapChangerQuery = results['data']['results']['bindings'] return TapChangerQuery - + def get_all_energy_sources(gapps, model_mrid): QuerySourceMessage = """ # substation source - DistSubstation @@ -289,7 +290,7 @@ def get_all_energy_sources(gapps, model_mrid): results = gapps.query_data(query = QuerySourceMessage, timeout = 60) SourceQuery = results['data']['results']['bindings'] return SourceQuery - + def get_all_batteries(gapps, model_mrid): QueryBattMessage = """ # Storage - DistStorage @@ -299,7 +300,7 @@ def get_all_batteries(gapps, model_mrid): ?s r:type c:BatteryUnit. ?s c:IdentifiedObject.name ?name. ?pec c:PowerElectronicsConnection.PowerElectronicsUnit ?s. - + VALUES ?fdrid {"%s"} ?pec c:Equipment.EquipmentContainer ?fdr. ?fdr c:IdentifiedObject.mRID ?fdrid. @@ -309,7 +310,7 @@ def get_all_batteries(gapps, model_mrid): ?t c:Terminal.ConnectivityNode ?cn. bind(strafter(str(?cn),"#") as ?cnid). ?t c:IdentifiedObject.mRID ?termid. - + } GROUP by ?name ?eqid ?fdrid ?pecid ?termid ?cnid ORDER by ?name @@ -317,7 +318,7 @@ def get_all_batteries(gapps, model_mrid): results = gapps.query_data(query = QueryBattMessage, timeout = 60) BattQuery = results['data']['results']['bindings'] return BattQuery - + def get_all_photovoltaics(gapps, model_mrid): QueryPVMessage = """ PREFIX r: diff --git a/topology_processor/topo_tester.py b/topology_processor/topo_tester.py index 7a48b05..2580915 100644 --- a/topology_processor/topo_tester.py +++ b/topology_processor/topo_tester.py @@ -3,9 +3,9 @@ def _main(): import os, json, time from gridappsd import GridAPPSD, topics as t from gridappsd.topics import service_input_topic, service_output_topic - from distributedtopology import DistributedTopology - from topologydictionary import TopologyDictionary - from networkmodel import NetworkModel + from topology_processor.distributedtopology import DistributedTopology + from topology_processor.topologydictionary import TopologyDictionary + from topology_processor.networkmodel import NetworkModel os.environ['GRIDAPPSD_APPLICATION_ID'] = 'gridappsd-topology-processor' os.environ['GRIDAPPSD_APPLICATION_STATUS'] = 'STARTED' diff --git a/topology_processor/topologyprocessor.py b/topologyprocessor.py similarity index 97% rename from topology_processor/topologyprocessor.py rename to topologyprocessor.py index c41069d..23b59ff 100644 --- a/topology_processor/topologyprocessor.py +++ b/topologyprocessor.py @@ -46,9 +46,10 @@ import os, json, time from gridappsd import GridAPPSD, topics as t from gridappsd.topics import service_input_topic, service_output_topic -from distributedtopology import DistributedTopology -from topologydictionary import TopologyDictionary -from networkmodel import NetworkModel + +from topology_processor.distributedtopology import DistributedTopology +from topology_processor.topologydictionary import TopologyDictionary +from topology_processor.networkmodel import NetworkModel class TopologyProcessor(GridAPPSD): diff --git a/topology_processor/topologyservice.py b/topologyservice.py similarity index 97% rename from topology_processor/topologyservice.py rename to topologyservice.py index 2778eee..3bf5c22 100644 --- a/topology_processor/topologyservice.py +++ b/topologyservice.py @@ -46,9 +46,9 @@ import os, time, json, argparse from gridappsd import GridAPPSD, topics as t from gridappsd.topics import service_output_topic, simulation_input_topic, simulation_output_topic -from distributedtopology import DistributedTopology -from topologydictionary import TopologyDictionary -from networkmodel import NetworkModel +from topology_processor.distributedtopology import DistributedTopology +from topology_processor.topologydictionary import TopologyDictionary +from topology_processor.networkmodel import NetworkModel class TopologyService(GridAPPSD):