Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Library release #20

Merged
merged 2 commits into from
Feb 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -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 = [
Expand Down
38 changes: 37 additions & 1 deletion topology_processor/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -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")


19 changes: 19 additions & 0 deletions topology_processor/blazegraph.py
Original file line number Diff line number Diff line change
@@ -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
52 changes: 28 additions & 24 deletions topology_processor/distributedtopology.py
Original file line number Diff line number Diff line change
@@ -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():

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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'])
Expand All @@ -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
Expand Down
2 changes: 1 addition & 1 deletion topology_processor/networkmodel.py
Original file line number Diff line number Diff line change
@@ -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):

Expand Down
27 changes: 14 additions & 13 deletions topology_processor/topo_meas_queries.py
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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="""
Expand All @@ -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.
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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.
Expand All @@ -309,15 +310,15 @@ 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
"""%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: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
Expand Down
6 changes: 3 additions & 3 deletions topology_processor/topo_tester.py
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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):

Expand Down
6 changes: 3 additions & 3 deletions topology_processor/topologyservice.py → topologyservice.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):

Expand Down