From 23e9fa498ff3b1653e5bd25bc83e0b611fc329b5 Mon Sep 17 00:00:00 2001 From: tonya1 Date: Mon, 17 Jul 2023 14:51:11 -0700 Subject: [PATCH 01/14] Update startup scripts to support the AUTOSTART environment variable --- entrypoint.sh | 11 ++++++++--- run-gridappsd.sh | 9 +++++++-- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/entrypoint.sh b/entrypoint.sh index ca3a5c413..6374fd248 100755 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -11,9 +11,14 @@ if [ "$1" = "gridappsd" ]; then sudo pip install -q --disable-pip-version-check -r $reqfile done - # Run tail -f /dev/null to keep the container running and waiting for connection - echo "[Entrypoint] Waiting for connection" - tail -f /dev/null + + if [ "${AUTOSTART:-0}" != "0" ]; then + /gridappsd/run-gridappsd.sh + else + # Run tail -f /dev/null to keep the container running and waiting for connection + echo "[Entrypoint] Waiting for connection" + tail -f /dev/null + fi elif [ "$1" = "version" -o "$1" = "-v" -o "$1" = "--version" ]; then echo -n "version: " cat /gridappsd/dockerbuildversion.txt diff --git a/run-gridappsd.sh b/run-gridappsd.sh index a0eee2911..061324c89 100755 --- a/run-gridappsd.sh +++ b/run-gridappsd.sh @@ -22,10 +22,15 @@ if [ -d /gridappsd/log ]; then /bin/rm -rf /gridappsd/log/* 2 > /dev/null fi +JAVA_OPTIONS="" +if [ "${AUTOSTART:-0}" != "0" ]; then + JAVA_OPTIONS=" -Dgosh.args=--nointeractive " +fi + # If the DEBUG environmental variable is set and is not 0 # then expose the port for remote debugging. if [ "${DEBUG:-0}" != "0" ]; then - java -agentlib:jdwp=transport=dt_socket,server=y,address=8000,suspend=n -jar lib/run.bnd.jar + java ${JAVA_OPTIONS} -agentlib:jdwp=transport=dt_socket,server=y,address=8000,suspend=n -jar lib/run.bnd.jar else - java -jar lib/run.bnd.jar + java ${JAVA_OPTIONS} -jar lib/run.bnd.jar fi From faa2d4e0cfabe320e66e943c6ff5bc81a8e236f1 Mon Sep 17 00:00:00 2001 From: poorva1209 Date: Fri, 5 Jan 2024 13:39:55 -0800 Subject: [PATCH 02/14] resolved bugs to start multiple simulations and services within multiple simulations --- .../pnnl/goss/gridappsd/service/ServiceManagerImpl.java | 2 -- .../goss/gridappsd/simulation/SimulationManagerImpl.java | 2 +- .../pnnl/goss/gridappsd/simulation/SimulationProcess.java | 8 ++++---- services/helicsgossbridge/service/helics_goss_bridge.py | 6 +++--- 4 files changed, 8 insertions(+), 10 deletions(-) diff --git a/gov.pnnl.goss.gridappsd/src/gov/pnnl/goss/gridappsd/service/ServiceManagerImpl.java b/gov.pnnl.goss.gridappsd/src/gov/pnnl/goss/gridappsd/service/ServiceManagerImpl.java index 230dae5c0..53812beef 100755 --- a/gov.pnnl.goss.gridappsd/src/gov/pnnl/goss/gridappsd/service/ServiceManagerImpl.java +++ b/gov.pnnl.goss.gridappsd/src/gov/pnnl/goss/gridappsd/service/ServiceManagerImpl.java @@ -417,8 +417,6 @@ public List listRunningServices(String serviceId, String simula if(instance.getService_info().getId().equals(serviceId)){ if(simulationId!=null && instance.getSimulation_id().equals(simulationId)) result.add(instance); - else - result.add(instance); } } return result; diff --git a/gov.pnnl.goss.gridappsd/src/gov/pnnl/goss/gridappsd/simulation/SimulationManagerImpl.java b/gov.pnnl.goss.gridappsd/src/gov/pnnl/goss/gridappsd/simulation/SimulationManagerImpl.java index d8e28fbf0..27f85d9d0 100755 --- a/gov.pnnl.goss.gridappsd/src/gov/pnnl/goss/gridappsd/simulation/SimulationManagerImpl.java +++ b/gov.pnnl.goss.gridappsd/src/gov/pnnl/goss/gridappsd/simulation/SimulationManagerImpl.java @@ -158,7 +158,7 @@ public void resumeSimulation(String simulationId){ } @Override public void endSimulation(String simulationId){ - client.publish(GridAppsDConstants.topic_COSIM_input, "{\"command\": \"stop\"}"); + client.publish(GridAppsDConstants.topic_COSIM_input+"."+simulationId, "{\"command\": \"stop\"}"); } diff --git a/gov.pnnl.goss.gridappsd/src/gov/pnnl/goss/gridappsd/simulation/SimulationProcess.java b/gov.pnnl.goss.gridappsd/src/gov/pnnl/goss/gridappsd/simulation/SimulationProcess.java index 3bfab0f38..81323d0f7 100644 --- a/gov.pnnl.goss.gridappsd/src/gov/pnnl/goss/gridappsd/simulation/SimulationProcess.java +++ b/gov.pnnl.goss.gridappsd/src/gov/pnnl/goss/gridappsd/simulation/SimulationProcess.java @@ -186,7 +186,7 @@ else if(simulationConfig.getSimulator().equals(gridlabdConstant)){ //Subscribe to fncs-goss-bridge output topic GossFncsResponseEvent gossFncsResponseEvent = new GossFncsResponseEvent(logManager, isInitialized, isFinished, simulationId); - client.subscribe("/topic/"+GridAppsDConstants.topic_COSIM_output, gossFncsResponseEvent); + client.subscribe("/topic/"+GridAppsDConstants.topic_COSIM_output+"."+simulationId, gossFncsResponseEvent); logManager.info(ProcessStatus.RUNNING, simulationId, "Checking if co-simulation is initialized, currently "+isInitialized.isInited); @@ -196,7 +196,7 @@ else if(simulationConfig.getSimulator().equals(gridlabdConstant)){ //TODO add limiting how long it checks for initialized, or cancel if the fncs process exits //This call would return true/false for initialization and simulation output of time step 0. - client.publish(GridAppsDConstants.topic_COSIM_input, "{\"command\": \"isInitialized\"}"); + client.publish(GridAppsDConstants.topic_COSIM_input+"."+simulationId, "{\"command\": \"isInitialized\"}"); initAttempts++; Thread.sleep(1000); @@ -217,7 +217,7 @@ else if(simulationConfig.getSimulator().equals(gridlabdConstant)){ } //call to stop the simulation - client.publish(GridAppsDConstants.topic_COSIM_input, "{\"command\": \"stop\"}"); + client.publish(GridAppsDConstants.topic_COSIM_input+"."+simulationId, "{\"command\": \"stop\"}"); logManager.info(ProcessStatus.COMPLETE, simulationId, "Simulation "+simulationId+" complete"); } catch(Exception e){ @@ -251,7 +251,7 @@ private void startSimulation(GossFncsResponseEvent gossEvent, SimulationConfig s // Send the start simulation command to the fncsgossbridge so that it runs it's time loop to move the fncs simulation forward logManager.debug(ProcessStatus.RUNNING, simulationId, "Sending start simulation to bridge."); String message = "{\"command\": \"StartSimulation\"}"; - client.publish(GridAppsDConstants.topic_COSIM_input, message); + client.publish(GridAppsDConstants.topic_COSIM_input+"."+simulationId, message); } private void watch(final Process process, String processName) { diff --git a/services/helicsgossbridge/service/helics_goss_bridge.py b/services/helicsgossbridge/service/helics_goss_bridge.py index 1df160cde..b9d0608f5 100644 --- a/services/helicsgossbridge/service/helics_goss_bridge.py +++ b/services/helicsgossbridge/service/helics_goss_bridge.py @@ -414,7 +414,7 @@ def on_message(self, headers, msg): message['response'] = str(self._is_initialized) t_now = datetime.utcnow() message['timestamp'] = int(time.mktime(t_now.timetuple())) - self._gad_connection.send(self._simulation_manager_input_topic , json.dumps(message)) + self._gad_connection.send(self._simulation_manager_input_topic+"."+self._simulation_id , json.dumps(message)) elif json_msg.get('command', '') == 'update': json_msg['input']["time_received"] = time.perf_counter() message['command'] = 'update' @@ -606,7 +606,7 @@ def run_simulation(self): log.debug(f"Simulation finished in {time.perf_counter() - simulation_run_time_start} seconds.") message['command'] = 'simulationFinished' del message['output'] - self._gad_connection.send(self._simulation_manager_input_topic, json.dumps(message)) + self._gad_connection.send(self._simulation_manager_input_topic+"."+self._simulation_id, json.dumps(message)) log.info(f'Simulation {self._simulation_id} has finished.') self._gad_connection.send_simulation_status('COMPLETE', f'Simulation {self._simulation_id} has finished.', 'INFO') except Exception as e: @@ -630,7 +630,7 @@ def _register_with_goss(self): self._gad_connection = GridAPPSD(self._simulation_id) log.debug("Successfully registered with the GridAPPS-D platform.") self._gad_connection.subscribe(topics.simulation_input_topic(self._simulation_id), self.on_message) - self._gad_connection.subscribe("/topic/goss.gridappsd.cosim.input", self.on_message) + self._gad_connection.subscribe("/topic/goss.gridappsd.cosim.input."+self._simulation_id, self.on_message) except Exception as e: log.error("An error occurred when trying to register with the GridAPPS-D platform!", exc_info=True) From 344bebdd5fbbfee672fbf3c31c60724517e98375 Mon Sep 17 00:00:00 2001 From: Sharma Date: Fri, 5 Jan 2024 14:16:54 -0800 Subject: [PATCH 03/14] Auto-starting context_manager as service with cim-graph 1.0 --- .../distributed/FieldBusManagerImpl.java | 691 +++++++++--------- .../gridappsd/dto/field/RequestField.java | 27 + requirements.txt | 1 + services/context_manager.config | 14 + 4 files changed, 396 insertions(+), 337 deletions(-) create mode 100644 gov.pnnl.goss.gridappsd/src/gov/pnnl/goss/gridappsd/dto/field/RequestField.java create mode 100644 services/context_manager.config diff --git a/gov.pnnl.goss.gridappsd/src/gov/pnnl/goss/gridappsd/distributed/FieldBusManagerImpl.java b/gov.pnnl.goss.gridappsd/src/gov/pnnl/goss/gridappsd/distributed/FieldBusManagerImpl.java index f9347619e..438c0647d 100644 --- a/gov.pnnl.goss.gridappsd/src/gov/pnnl/goss/gridappsd/distributed/FieldBusManagerImpl.java +++ b/gov.pnnl.goss.gridappsd/src/gov/pnnl/goss/gridappsd/distributed/FieldBusManagerImpl.java @@ -1,323 +1,362 @@ - package gov.pnnl.goss.gridappsd.distributed; - - import java.io.Serializable; - import java.util.ArrayList; - import java.util.Dictionary; - import java.util.HashMap; - import java.util.List; - import java.util.Map; - import java.util.stream.Collectors; - - import org.apache.felix.dm.annotation.api.Component; - import org.apache.felix.dm.annotation.api.ConfigurationDependency; - import org.apache.felix.dm.annotation.api.ServiceDependency; - import org.apache.felix.dm.annotation.api.Start; - import org.apache.http.auth.Credentials; - import org.apache.http.auth.UsernamePasswordCredentials; - import org.json.JSONArray; - import org.json.JSONObject; - - import com.google.gson.Gson; - import com.google.gson.JsonElement; - import com.google.gson.JsonObject; - import com.google.gson.JsonParser; - - import gov.pnnl.goss.gridappsd.api.DataManager; - import gov.pnnl.goss.gridappsd.api.FieldBusManager; - import gov.pnnl.goss.gridappsd.api.LogManager; - import gov.pnnl.goss.gridappsd.api.PowergridModelDataManager; - import gov.pnnl.goss.gridappsd.api.ServiceManager; - import gov.pnnl.goss.gridappsd.dto.LogMessage.ProcessStatus; - import gov.pnnl.goss.gridappsd.dto.PowergridModelDataRequest; - import gov.pnnl.goss.gridappsd.dto.ServiceInfo; - import gov.pnnl.goss.gridappsd.dto.field.Feeder; - import gov.pnnl.goss.gridappsd.dto.field.RequestFieldContext; - import gov.pnnl.goss.gridappsd.dto.field.Root; - import gov.pnnl.goss.gridappsd.dto.field.SecondaryArea; - import gov.pnnl.goss.gridappsd.dto.field.SwitchArea; - import gov.pnnl.goss.gridappsd.utils.GridAppsDConstants; - import pnnl.goss.core.Client; - import pnnl.goss.core.Client.PROTOCOL; - import pnnl.goss.core.ClientFactory; - import pnnl.goss.core.DataResponse; - import pnnl.goss.core.GossResponseEvent; - import pnnl.goss.core.Request.RESPONSE_FORMAT; - import pnnl.goss.core.Response; - import pnnl.goss.core.security.SecurityConfig; - - @Component - public class FieldBusManagerImpl implements FieldBusManager { - - private static final String CONFIG_PID = "pnnl.goss.gridappsd"; - private Dictionary configurationProperties; - - String topology_reponse; - String topicPrefix = "goss.gridappsd.process.request.field"; - String topicContext = topicPrefix + ".context"; - - @ServiceDependency - ClientFactory clientFactory; - - @ServiceDependency - private volatile DataManager dataManager; - - @ServiceDependency - private volatile ServiceManager serviceManager; - - @ServiceDependency - private volatile LogManager logManager; - - private volatile TopologyRequestProcess topology; - - @ServiceDependency - SecurityConfig securityConfig; - - @ServiceDependency - PowergridModelDataManager powergridModelDataManager; - - Client client; - - Map> messageBus_measIds_map = new HashMap>(); - //Map measId_messageBus_map = new HashMap(); - - String fieldModelId = null; - - // FileWriter writer = null; - - public FieldBusManagerImpl() { - System.out.println("Starting FieldBusManager"); - } - - @Start - public void start() { - - try { - - Credentials credentials = new UsernamePasswordCredentials(securityConfig.getManagerUser(), - securityConfig.getManagerPassword()); - client = clientFactory.create(PROTOCOL.STOMP, credentials, true); - - ServiceInfo serviceInfo = serviceManager.getService("gridappsd-topology-daemon"); - if (serviceInfo == null) { - logManager.warn(ProcessStatus.RUNNING, null, - "Topology deamon service is not available. Stopping FieldBusManager."); - return; - } - - fieldModelId = getFieldModelMrid(); - if (fieldModelId == null) { - logManager.warn(ProcessStatus.RUNNING, null, - "Field model mrid is not available. Stopping FieldBusManager. " - + "Check conf/pnnl.goss.gridappsd.cfg file and add field.model.mrid key with value of deployed field model mrid. "); - return; - } - - topology = new TopologyRequestProcess(fieldModelId, client, dataManager, securityConfig); - topology.start(); - - this.publishDeviceOutput(); - - } catch (Exception e) { - e.printStackTrace(); +package gov.pnnl.goss.gridappsd.distributed; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Dictionary; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import org.apache.felix.dm.annotation.api.Component; +import org.apache.felix.dm.annotation.api.ConfigurationDependency; +import org.apache.felix.dm.annotation.api.ServiceDependency; +import org.apache.felix.dm.annotation.api.Start; +import org.apache.http.auth.Credentials; +import org.apache.http.auth.UsernamePasswordCredentials; +import org.json.JSONArray; +import org.json.JSONObject; + +import com.google.gson.Gson; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; + +import gov.pnnl.goss.gridappsd.api.DataManager; +import gov.pnnl.goss.gridappsd.api.FieldBusManager; +import gov.pnnl.goss.gridappsd.api.LogManager; +import gov.pnnl.goss.gridappsd.api.PowergridModelDataManager; +import gov.pnnl.goss.gridappsd.api.ServiceManager; +import gov.pnnl.goss.gridappsd.dto.LogMessage.ProcessStatus; +import gov.pnnl.goss.gridappsd.dto.PowergridModelDataRequest; +import gov.pnnl.goss.gridappsd.dto.ServiceInfo; +import gov.pnnl.goss.gridappsd.dto.field.Feeder; +import gov.pnnl.goss.gridappsd.dto.field.RequestField; +import gov.pnnl.goss.gridappsd.dto.field.Root; +import gov.pnnl.goss.gridappsd.dto.field.SecondaryArea; +import gov.pnnl.goss.gridappsd.dto.field.SwitchArea; +import gov.pnnl.goss.gridappsd.utils.GridAppsDConstants; +import pnnl.goss.core.Client; +import pnnl.goss.core.Client.PROTOCOL; +import pnnl.goss.core.ClientFactory; +import pnnl.goss.core.DataResponse; +import pnnl.goss.core.GossResponseEvent; +import pnnl.goss.core.Request.RESPONSE_FORMAT; +import pnnl.goss.core.Response; +import pnnl.goss.core.security.SecurityConfig; + +@Component +public class FieldBusManagerImpl implements FieldBusManager { + + private static final String CONFIG_PID = "pnnl.goss.gridappsd"; + private Dictionary configurationProperties; + + String topology_reponse; + String topicPrefix = "goss.gridappsd.process.request.field"; + + @ServiceDependency + ClientFactory clientFactory; + + @ServiceDependency + private volatile DataManager dataManager; + + @ServiceDependency + private volatile ServiceManager serviceManager; + + @ServiceDependency + private volatile LogManager logManager; + + private volatile TopologyRequestProcess topology; + + @ServiceDependency + SecurityConfig securityConfig; + + @ServiceDependency + PowergridModelDataManager powergridModelDataManager; + + Client client; + + Map> messageBus_measIds_map = new HashMap>(); + //Map measId_messageBus_map = new HashMap(); + + String fieldModelId = null; + + // FileWriter writer = null; + + public FieldBusManagerImpl() { + System.out.println("Starting FieldBusManager"); + } + + @Start + public void start() { + + try { + + Credentials credentials = new UsernamePasswordCredentials(securityConfig.getManagerUser(), + securityConfig.getManagerPassword()); + client = clientFactory.create(PROTOCOL.STOMP, credentials, true); + + ServiceInfo serviceInfo = serviceManager.getService("gridappsd-topology-daemon"); + if (serviceInfo == null) { + logManager.warn(ProcessStatus.RUNNING, null, + "Topology deamon service is not available. Stopping FieldBusManager."); + return; } - + + fieldModelId = getFieldModelMrid(); + if (fieldModelId == null) { + logManager.warn(ProcessStatus.RUNNING, null, + "Field model mrid is not available. Stopping FieldBusManager. " + + "Check conf/pnnl.goss.gridappsd.cfg file and add field.model.mrid key with value of deployed field model mrid. "); + return; + } + + topology = new TopologyRequestProcess(fieldModelId, client, dataManager, securityConfig); + topology.start(); + + this.publishDeviceOutput(); + + } catch (Exception e) { + e.printStackTrace(); } - - @Override - public Serializable handleRequest(String request_queue, Serializable request) { - - Feeder responseFeeder = null; - - if (request_queue.endsWith("context")) { - - RequestFieldContext requestFieldContext = RequestFieldContext.parse(request.toString()); - if (requestFieldContext.areaId == null) - return topology.root.feeders; - else if(requestFieldContext.areaId.equals(topology.root.feeders.message_bus_id)) - return topology.root.feeders; - else { - for (SwitchArea switchArea : topology.root.feeders.switch_areas) { - if (requestFieldContext.areaId.equals(switchArea.message_bus_id)) - return switchArea; - for (SecondaryArea secondaryArea : switchArea.secondary_areas) { - if (requestFieldContext.areaId.equals(secondaryArea.message_bus_id)) - return secondaryArea; - } + + } + + @Override + public Serializable handleRequest(String request_queue, Serializable request) { + + Feeder responseFeeder = null; + RequestField requestField = RequestField.parse(request.toString()); + + if (requestField.request_type.equals("get_context")) { + + if (requestField.areaId == null) + return topology.root.feeders; + else if(requestField.areaId.equals(topology.root.feeders.message_bus_id)) + return topology.root.feeders; + else { + for (SwitchArea switchArea : topology.root.feeders.switch_areas) { + if (requestField.areaId.equals(switchArea.message_bus_id)) + return switchArea; + for (SecondaryArea secondaryArea : switchArea.secondary_areas) { + if (requestField.areaId.equals(secondaryArea.message_bus_id)) + return secondaryArea; } } - } - return responseFeeder; } - - public void publishDeviceOutput() { - - client.subscribe(GridAppsDConstants.topic_simulationOutput + ".>", new GossResponseEvent() { - - @Override - public void onMessage(Serializable response) { - - DataResponse event = (DataResponse) response; - String simulationId = event.getDestination().substring(event.getDestination().lastIndexOf(".") + 1, - event.getDestination().length()); - String simOutputStr = event.getData().toString(); - JsonObject simOutputJsonObj = null; - - JsonParser parser = new JsonParser(); - JsonElement simOutputObject = parser.parse(simOutputStr); - - if (simOutputObject.isJsonObject()) { - simOutputJsonObj = simOutputObject.getAsJsonObject(); - } - - JsonObject tempObj = simOutputJsonObj.getAsJsonObject("message"); - Map expectedOutputMap = tempObj.getAsJsonObject("measurements").entrySet().stream() - .collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue())); - - try { - - for (String measurementMrid : expectedOutputMap.keySet()) { - - String messageBusId = null; - if (topology.measId_messageBus_map.get(measurementMrid) != null) { - messageBusId = "goss.gridappsd.field.simulation.output." + simulationId + "." - + topology.measId_messageBus_map.get(measurementMrid); - } else { - messageBusId = "goss.gridappsd.field.simulation.output." + simulationId + "." - + topology.root.feeders.message_bus_id; - } - - JsonObject obj = new JsonObject(); - obj.add(measurementMrid, expectedOutputMap.get(measurementMrid)); - - client.publish(messageBusId, obj.toString()); + else if (requestField.request_type.equals("is_initilized")) { + + JsonObject obj = new JsonObject(); + try { + if (topology.root.feeders != null){ + obj.addProperty("initialized",true); + } + else{ + obj.addProperty("initialized",false); + } + }catch(NullPointerException e){ + obj.addProperty("initialized",false); + return obj.toString(); + } + + return obj.toString(); + } + + return null; + } + + public void publishDeviceOutput() { + + client.subscribe(GridAppsDConstants.topic_simulationOutput + ".>", new GossResponseEvent() { + + @Override + public void onMessage(Serializable response) { + + DataResponse event = (DataResponse) response; + String simulationId = event.getDestination().substring(event.getDestination().lastIndexOf(".") + 1, + event.getDestination().length()); + String simOutputStr = event.getData().toString(); + JsonObject simOutputJsonObj = null; + + JsonParser parser = new JsonParser(); + JsonElement simOutputObject = parser.parse(simOutputStr); + + if (simOutputObject.isJsonObject()) { + simOutputJsonObj = simOutputObject.getAsJsonObject(); + } + + JsonObject tempObj = simOutputJsonObj.getAsJsonObject("message"); + Map expectedOutputMap = tempObj.getAsJsonObject("measurements").entrySet().stream() + .collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue())); + + try { + + for (String measurementMrid : expectedOutputMap.keySet()) { + + String messageBusId = null; + if (topology.measId_messageBus_map.get(measurementMrid) != null) { + messageBusId = "goss.gridappsd.field.simulation.output." + simulationId + "." + + topology.measId_messageBus_map.get(measurementMrid); + } else { + messageBusId = "goss.gridappsd.field.simulation.output." + simulationId + "." + + topology.root.feeders.message_bus_id; } - - } catch (Exception e1) { - e1.printStackTrace(); + + JsonObject obj = new JsonObject(); + obj.add(measurementMrid, expectedOutputMap.get(measurementMrid)); + + client.publish(messageBusId, obj.toString()); + } - - + + } catch (Exception e1) { + e1.printStackTrace(); } - - }); - - } - - @ConfigurationDependency(pid = CONFIG_PID) - public synchronized void updated(Dictionary config) { - this.configurationProperties = config; - } - - public String getFieldModelMrid() { - if (this.configurationProperties != null) { - Object value = this.configurationProperties.get("field.model.mrid"); - if (value != null) - return value.toString(); + + } - return null; - } - + + }); + } - - class TopologyRequest implements Serializable { - - private static final long serialVersionUID = 4279262793871885409L; - - String requestType = "GET_SWITCH_AREAS"; - String modelID = null; - String resultFormat = "JSON"; - - @Override - public String toString() { - Gson gson = new Gson(); - return gson.toJson(this); - } - + + @ConfigurationDependency(pid = CONFIG_PID) + public synchronized void updated(Dictionary config) { + this.configurationProperties = config; } - - class TopologyRequestProcess extends Thread { - - String fieldModelMrid; - Client client; - DataManager dataManager; - SecurityConfig securityConfig; - Root root = null; - Map> messageBus_measIds_map = new HashMap>(); - Map measId_messageBus_map = new HashMap(); - - public TopologyRequestProcess(String fieldModelMrid, Client client, DataManager dataManager, - SecurityConfig securityConfig) { - this.fieldModelMrid = fieldModelMrid; - this.client = client; - this.dataManager = dataManager; - this.securityConfig = securityConfig; + + public String getFieldModelMrid() { + if (this.configurationProperties != null) { + Object value = this.configurationProperties.get("field.model.mrid"); + if (value != null) + return value.toString(); } - - @Override - public void run() { - try { - Gson gson = new Gson(); - TopologyRequest request = new TopologyRequest(); - request.modelID = fieldModelMrid; - Serializable topoResponse = client.getResponse(request.toString(), "goss.gridappsd.request.data.topology", + return null; + } + +} + +class TopologyRequest implements Serializable { + + private static final long serialVersionUID = 4279262793871885409L; + + String requestType = "GET_SWITCH_AREAS"; + String modelID = null; + String resultFormat = "JSON"; + + @Override + public String toString() { + Gson gson = new Gson(); + return gson.toJson(this); + } + +} + +class TopologyRequestProcess extends Thread { + + String fieldModelMrid; + Client client; + DataManager dataManager; + SecurityConfig securityConfig; + Root root = null; + Map> messageBus_measIds_map = new HashMap>(); + Map measId_messageBus_map = new HashMap(); + + public TopologyRequestProcess(String fieldModelMrid, Client client, DataManager dataManager, + SecurityConfig securityConfig) { + this.fieldModelMrid = fieldModelMrid; + this.client = client; + this.dataManager = dataManager; + this.securityConfig = securityConfig; + } + + @Override + public void run() { + try { + Gson gson = new Gson(); + TopologyRequest request = new TopologyRequest(); + request.modelID = fieldModelMrid; + Serializable topoResponse = client.getResponse(request.toString(), "goss.gridappsd.request.data.topology", + RESPONSE_FORMAT.JSON); + int attempt = 1; + if (topoResponse == null && attempt < 6) { + // May have to wait for Topology processor to initialize + topoResponse = client.getResponse(request.toString(), "goss.gridappsd.request.data.topology", RESPONSE_FORMAT.JSON); - int attempt = 1; - if (topoResponse == null && attempt < 6) { - // May have to wait for Topology processor to initialize - topoResponse = client.getResponse(request.toString(), "goss.gridappsd.request.data.topology", - RESPONSE_FORMAT.JSON); - Thread.sleep(1000); - attempt++; - } - if (topoResponse != null && (topoResponse instanceof DataResponse)) { - String str = ((DataResponse) topoResponse).getData().toString(); - root = gson.fromJson(str, Root.class); - } else { - root = gson.fromJson(topoResponse.toString(), Root.class); + Thread.sleep(1000); + attempt++; + } + if (topoResponse != null && (topoResponse instanceof DataResponse)) { + String str = ((DataResponse) topoResponse).getData().toString(); + root = gson.fromJson(str, Root.class); + } else { + root = gson.fromJson(topoResponse.toString(), Root.class); + } + + /* + * feederList = root.feeders; if(root == null || feederList == null + * || feederList.size() == 0){ throw new + * Exception("No Feeder available to create field message bus"); } + */ + + root.feeders.message_bus_id = root.feeders.feeder_id; + int switch_area_index = 0; + for (SwitchArea switchArea : root.feeders.switch_areas) { + switchArea.message_bus_id = root.feeders.feeder_id + "." + switch_area_index; + int secondary_area_index = 0; + for (SecondaryArea secondaryArea : switchArea.secondary_areas) { + secondaryArea.message_bus_id = root.feeders.feeder_id + "." + switch_area_index + "." + + secondary_area_index; + secondary_area_index++; } - - /* - * feederList = root.feeders; if(root == null || feederList == null - * || feederList.size() == 0){ throw new - * Exception("No Feeder available to create field message bus"); } - */ - - root.feeders.message_bus_id = root.feeders.feeder_id; - int switch_area_index = 0; - for (SwitchArea switchArea : root.feeders.switch_areas) { - switchArea.message_bus_id = root.feeders.feeder_id + "." + switch_area_index; - int secondary_area_index = 0; - for (SecondaryArea secondaryArea : switchArea.secondary_areas) { - secondaryArea.message_bus_id = root.feeders.feeder_id + "." + switch_area_index + "." - + secondary_area_index; - secondary_area_index++; + switch_area_index++; + } + + this.getFieldMeasurementIds(fieldModelMrid); + + } catch (Exception e) { + e.printStackTrace(); + } + + } + + public void getFieldMeasurementIds(String fieldModelMrid) { + + PowergridModelDataRequest request = new PowergridModelDataRequest(); + request.modelId = fieldModelMrid; + request.requestType = PowergridModelDataRequest.RequestType.QUERY_OBJECT_MEASUREMENTS.toString(); + Response response = null; + List measurementList = new ArrayList(); + + try { + + // Get Feeder level measurement ids + for (String equipmentId : root.feeders.addressable_equipment) { + request.objectId = equipmentId; + response = dataManager.processDataRequest(request, "powergridmodel", null, null, + securityConfig.getManagerUser()); + if (response != null && (response instanceof DataResponse)) { + String str = ((DataResponse) response).getData().toString(); + JSONArray array = new JSONArray(str); + measurementList.clear(); + for (int i = 0; i < array.length(); i++) { + JSONObject object = array.getJSONObject(i); + String measid = object.getString("measid"); + measId_messageBus_map.put(measid, root.feeders.message_bus_id); + measurementList.add(measid); } - switch_area_index++; + messageBus_measIds_map.put(root.feeders.message_bus_id, measurementList); } - - this.getFieldMeasurementIds(fieldModelMrid); - - } catch (Exception e) { - e.printStackTrace(); + } - - } - - public void getFieldMeasurementIds(String fieldModelMrid) { - - PowergridModelDataRequest request = new PowergridModelDataRequest(); - request.modelId = fieldModelMrid; - request.requestType = PowergridModelDataRequest.RequestType.QUERY_OBJECT_MEASUREMENTS.toString(); - Response response = null; - List measurementList = new ArrayList(); - - try { - - // Get Feeder level measurement ids - for (String equipmentId : root.feeders.addressable_equipment) { + + // Get switch level measurement ids + for (SwitchArea switchArea : root.feeders.switch_areas) { + + for (String equipmentId : switchArea.addressable_equipment) { request.objectId = equipmentId; response = dataManager.processDataRequest(request, "powergridmodel", null, null, securityConfig.getManagerUser()); @@ -328,19 +367,17 @@ public void getFieldMeasurementIds(String fieldModelMrid) { for (int i = 0; i < array.length(); i++) { JSONObject object = array.getJSONObject(i); String measid = object.getString("measid"); - measId_messageBus_map.put(measid, root.feeders.message_bus_id); + measId_messageBus_map.put(measid, switchArea.message_bus_id); measurementList.add(measid); } - messageBus_measIds_map.put(root.feeders.message_bus_id, measurementList); + messageBus_measIds_map.put(switchArea.message_bus_id, measurementList); } - } - - // Get switch level measurement ids - for (SwitchArea switchArea : root.feeders.switch_areas) { - - for (String equipmentId : switchArea.addressable_equipment) { - request.objectId = equipmentId; + + // Get Secondary level measurement ids + for (SecondaryArea secondaryArea : switchArea.secondary_areas) { + for (String equipmentid : secondaryArea.addressable_equipment) { + request.objectId = equipmentid; response = dataManager.processDataRequest(request, "powergridmodel", null, null, securityConfig.getManagerUser()); if (response != null && (response instanceof DataResponse)) { @@ -350,39 +387,19 @@ public void getFieldMeasurementIds(String fieldModelMrid) { for (int i = 0; i < array.length(); i++) { JSONObject object = array.getJSONObject(i); String measid = object.getString("measid"); - measId_messageBus_map.put(measid, switchArea.message_bus_id); + measId_messageBus_map.put(measid, secondaryArea.message_bus_id); measurementList.add(measid); } - messageBus_measIds_map.put(switchArea.message_bus_id, measurementList); - } - } - - // Get Secondary level measurement ids - for (SecondaryArea secondaryArea : switchArea.secondary_areas) { - for (String equipmentid : secondaryArea.addressable_equipment) { - request.objectId = equipmentid; - response = dataManager.processDataRequest(request, "powergridmodel", null, null, - securityConfig.getManagerUser()); - if (response != null && (response instanceof DataResponse)) { - String str = ((DataResponse) response).getData().toString(); - JSONArray array = new JSONArray(str); - measurementList.clear(); - for (int i = 0; i < array.length(); i++) { - JSONObject object = array.getJSONObject(i); - String measid = object.getString("measid"); - measId_messageBus_map.put(measid, secondaryArea.message_bus_id); - measurementList.add(measid); - } - messageBus_measIds_map.put(secondaryArea.message_bus_id, measurementList); - } + messageBus_measIds_map.put(secondaryArea.message_bus_id, measurementList); } } - } - } catch (Exception e) { - e.printStackTrace(); + } - + } catch (Exception e) { + e.printStackTrace(); } - + } + +} diff --git a/gov.pnnl.goss.gridappsd/src/gov/pnnl/goss/gridappsd/dto/field/RequestField.java b/gov.pnnl.goss.gridappsd/src/gov/pnnl/goss/gridappsd/dto/field/RequestField.java new file mode 100644 index 000000000..01d194673 --- /dev/null +++ b/gov.pnnl.goss.gridappsd/src/gov/pnnl/goss/gridappsd/dto/field/RequestField.java @@ -0,0 +1,27 @@ +package gov.pnnl.goss.gridappsd.dto.field; + +import java.io.Serializable; + +import com.google.gson.Gson; +import com.google.gson.JsonSyntaxException; + +public class RequestField implements Serializable { + + private static final long serialVersionUID = 3088063820447700212L; + + public String request_type = null; + public String areaId = null; + + public static RequestField parse(String jsonString) throws JsonSyntaxException { + Gson gson = new Gson(); + RequestField obj = gson.fromJson(jsonString, RequestField.class); + return obj; + } + + @Override + public String toString() { + Gson gson = new Gson(); + return gson.toJson(this); + } + +} diff --git a/requirements.txt b/requirements.txt index dde65da11..93ec936b7 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,3 +3,4 @@ remote_pdb durable-rules gridappsd-python +gridappsd-field-bus diff --git a/services/context_manager.config b/services/context_manager.config new file mode 100644 index 000000000..65bcd7c68 --- /dev/null +++ b/services/context_manager.config @@ -0,0 +1,14 @@ +{ + "id": "context_manager", + "description": "GridAPPS-D Context Manager for distributed applications/agents", + "creator": "PNNL", + "inputs": [], + "outputs": [], + "static_args": [], + "execution_path": "context_manager", + "type": "EXE", + "launch_on_startup": "true", + "prereqs": ["gridappsd-topology-daemon"], + "multiple_instances": "false", + "environmentVariables": [{"envName":"GRIDAPPSD_APPLICATION_ID","envValue":"context_manager"}] +} From 2407dde55206324beee91a45d4b636af77dddc06 Mon Sep 17 00:00:00 2001 From: "C. Allwardt" <3979063+craig8@users.noreply.github.com> Date: Wed, 10 Jan 2024 10:33:11 -0800 Subject: [PATCH 04/14] Update build-gridappsd-container --- build-gridappsd-container | 70 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 65 insertions(+), 5 deletions(-) diff --git a/build-gridappsd-container b/build-gridappsd-container index 89b0af39c..3f842ca03 100755 --- a/build-gridappsd-container +++ b/build-gridappsd-container @@ -1,7 +1,67 @@ -docker pull gridappsd/gridappsd_base:master +#!/usr/bin/env python3 -./gradlew clean -rm -rf gov.pnnl.goss/gridappsd/generated -./gradlew export +""" +Script for building the gridappsd container. -docker build --no-cache --network=host -t gridappsd:local . +This script pulls the gridappsd_base docker image, cleans the project, exports the project, and builds the gridappsd container. + +Usage: + python build-gridappsd-container [--output_version ] + +Arguments: + base_version (str): The version of the gridappsd_base docker image. + output_version (str, optional): The output tag version for local development. Default is "local". + +Example: + python build-gridappsd-container.py 2.3.0 --output_version 2.3.1 + +""" + +import argparse +import subprocess +import shutil + + +def execute(cmd: str | list[str]): + """ + Executes a command in the shell and prints the output. + + Args: + cmd (str | list[str]): The command to execute. If a string, it will be split into a list of arguments. + + Raises: + subprocess.CalledProcessError: If the command returns a non-zero exit code. + + """ + if isinstance(cmd, str): + cmd = cmd.split(" ") + + with subprocess.Popen(cmd, stdout=subprocess.PIPE, universal_newlines=True) as p: + for line in iter(p.stdout.readline, ""): + if line.strip(): + print(line.strip()) + + p.wait() + if p.returncode: + raise subprocess.CalledProcessError(p.returncode, cmd=" ".join(cmd)) + + + +if __name__ == '__main__': + + parser = argparse.ArgumentParser() + + parser.add_argument("base_version", + help="The gridappsd_base docker image version") + parser.add_argument("--output_version", default="local", + help="The output tag version for local development") + + opts = parser.parse_args() + + base_version = opts.base_version + + execute(f"docker pull gridappsd/gridappsd_base:{opts.base_version}") + execute("./gradlew clean") + shutil.rmtree("gov.pnnl.goss/gridappsd/generated", ignore_errors=True) + execute("./gradlew export") + execute(f"docker build --build-arg GRIDAPPSD_BASE_VERSION=:{opts.base_version} --no-cache --network=host -t gridappsd:{opts.output_version} .") From 67328ab78e6fc7bb070f3354378fe03e816db8fd Mon Sep 17 00:00:00 2001 From: "C. Allwardt" <3979063+craig8@users.noreply.github.com> Date: Tue, 30 Jan 2024 11:42:16 -0800 Subject: [PATCH 05/14] Added pre to the final install of requirements --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 4b5636870..5f26ef9bb 100644 --- a/Dockerfile +++ b/Dockerfile @@ -111,7 +111,7 @@ RUN chmod +x /usr/local/bin/opendsscmd && \ # before executing this script. COPY ./gov.pnnl.goss.gridappsd/generated/distributions/executable/run.bnd.jar /gridappsd/lib/run.bnd.jar -RUN pip install -r /gridappsd/requirements.txt && \ +RUN pip install --pre -r /gridappsd/requirements.txt && \ pip install -r /gridappsd/services/fncsgossbridge/requirements.txt && \ rm -rf /root/.cache/pip/wheels From 8857df94ac3d49dab69a57d91f504630e5bf90a4 Mon Sep 17 00:00:00 2001 From: poorva1209 Date: Tue, 30 Jan 2024 13:11:17 -0800 Subject: [PATCH 06/14] Update Dockerfile develop tag for python3.10 base --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 5f26ef9bb..729b1abb1 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -ARG GRIDAPPSD_BASE_VERSION=:master +ARG GRIDAPPSD_BASE_VERSION=:develop FROM gridappsd/gridappsd_base${GRIDAPPSD_BASE_VERSION} ARG TIMESTAMP From fbd3ba574488b88c5fdfcd6553a88a8085fb5b6e Mon Sep 17 00:00:00 2001 From: afisher1 <4552674+afisher1@users.noreply.github.com> Date: Mon, 8 Apr 2024 15:44:21 -0700 Subject: [PATCH 07/14] Adding optional automatic simulation pause after publish. --- .../service/helics_goss_bridge.py | 269 +++++++++++++----- 1 file changed, 195 insertions(+), 74 deletions(-) diff --git a/services/helicsgossbridge/service/helics_goss_bridge.py b/services/helicsgossbridge/service/helics_goss_bridge.py index b9d0608f5..2ee06ccc9 100644 --- a/services/helicsgossbridge/service/helics_goss_bridge.py +++ b/services/helicsgossbridge/service/helics_goss_bridge.py @@ -414,14 +414,16 @@ def on_message(self, headers, msg): message['response'] = str(self._is_initialized) t_now = datetime.utcnow() message['timestamp'] = int(time.mktime(t_now.timetuple())) - self._gad_connection.send(self._simulation_manager_input_topic+"."+self._simulation_id , json.dumps(message)) + self._gad_connection.send(self._simulation_manager_input_topic+"."+self._simulation_id , + json.dumps(message)) elif json_msg.get('command', '') == 'update': json_msg['input']["time_received"] = time.perf_counter() message['command'] = 'update' if self._filter_all_commands == False: self._simulation_command_queue.put(json.dumps(json_msg['input'])) elif json_msg.get('command', '') == 'StartSimulation': - self._gad_connection.send_simulation_status('STARTED', f"Simulation {self._simulation_id} has started.", 'INFO') + self._gad_connection.send_simulation_status('STARTED', f"Simulation {self._simulation_id} has started.", + 'INFO') if self._start_simulation == False: self._start_simulation = True elif json_msg.get('command', '') == 'CommOutage': @@ -465,7 +467,10 @@ def on_message(self, headers, msg): elif json_msg.get('command', '') == 'pause': if self._pause_simulation == True: log.warning('Pause command received but the simulation is already paused.') - self._gad_connection.send_simulation_status('PAUSED', 'Pause command received but the simulation is already paused.', 'WARN') + self._gad_connection.send_simulation_status('PAUSED', + 'Pause command received but the simulation is already ' + 'paused.', + 'WARN') else: self._pause_simulation = True log.info('The simulation has paused.') @@ -473,7 +478,10 @@ def on_message(self, headers, msg): elif json_msg.get('command', '') == 'resume': if self._pause_simulation == False: log.warning('Resume command received but the simulation is already running.') - self._gad_connection.send_simulation_status('RUNNING', 'Resume command received but the simulation is already running.', 'WARN') + self._gad_connection.send_simulation_status('RUNNING', + 'Resume command received but the simulation is already ' + 'running.', + 'WARN') else: self._pause_simulation = False log.info('The simulation has resumed.') @@ -481,7 +489,10 @@ def on_message(self, headers, msg): elif json_msg.get('command', '') == 'resumePauseAt': if self._pause_simulation == False: log.warning('The resumePauseAt command was received but the simulation is already running.') - self._gad_connection.send_simulation_status('RUNNING', 'The resumePauseAt command was received but the simulation is already running.', 'WARN') + self._gad_connection.send_simulation_status('RUNNING', + 'The resumePauseAt command was received but the ' + 'simulation is already running.', + 'WARN') else: self._pause_simulation = False log.info('The simulation has resumed.') @@ -489,7 +500,10 @@ def on_message(self, headers, msg): self._pause_simulation_at = self._simulation_time + json_msg.get('input', {}).get('pauseIn',-1) elif json_msg.get('command', '') == '': log.warning('The message received did not have a command key. Ignoring malformed message.') - self._gad_connection.send_simulation_status('RUNNING', 'The message received did not have a command key. Ignoring malformed message.', 'WARN') + self._gad_connection.send_simulation_status('RUNNING', + 'The message received did not have a command key. Ignoring ' + 'malformed message.', + 'WARN') except Exception as e: message_str = f'Error in processing command message:\n{msg}.\nError:\n{traceback.format_exc()}' log.error(message_str) @@ -512,7 +526,9 @@ def on_error(self, headers, message): def on_disconnected(self): self._stop_simulation = True - helics.helicsFederateGlobalError(self._helics_federate, 1, "HelicsGossBridge instance lost connection to GOSS bus.") + helics.helicsFederateGlobalError(self._helics_federate, + 1, + "HelicsGossBridge instance lost connection to GOSS bus.") self._close_helics_connection() def run_simulation(self): @@ -520,6 +536,8 @@ def run_simulation(self): run_realtime = self._simulation_request.get("simulation_config",{}).get("run_realtime",1) simulation_length = self._simulation_request.get("simulation_config",{}).get("duration",0) simulation_start = self._simulation_request.get("simulation_config",{}).get("start_time",0) + pause_after_measurements = self._simulation_request.get("simulation_config",{}).get("pause_after_measurements", + False) # New archiving variables set here # Once the simulation_config is sent directly from the ui, then we can use these, # Until then you can change the archive to have a default value for either the @@ -549,18 +567,28 @@ def run_simulation(self): begin_time_step = time.perf_counter() federate_state = helics.helicsFederateGetState(self._helics_federate) if federate_state == 4: - self._gad_connection.send_simulation_status("ERROR",f"The HELICS co-simulation for simulation {self._simulation_id} entered an error state for some unknown reason.", "ERROR") - log.error(f"The HELICS co-simulation for simulation {self._simulation_id} entered an error state for some unknown reason.") - raise RuntimeError(f"The HELICS co-simulation for simulation {self._simulation_id} entered an error state for some unknown reason.") + self._gad_connection.send_simulation_status("ERROR", + "The HELICS co-simulation for simulation " + f"{self._simulation_id} entered an error state for " + "some unknown reason.", + "ERROR") + log.error(f"The HELICS co-simulation for simulation {self._simulation_id} entered an error state " + "for some unknown reason.") + raise RuntimeError(f"The HELICS co-simulation for simulation {self._simulation_id} entered an " + "error state for some unknown reason.") self._simulation_time = current_time if self._stop_simulation == True: if federate_state == 2: - helics.helicsFederateGlobalError(self._helics_federate, 1, "Stopping the simulation prematurely at operator's request!") + helics.helicsFederateGlobalError(self._helics_federate, + 1, + "Stopping the simulation prematurely at operator's request!") break - self._gad_connection.send(f"goss.gridappsd.cosim.timestamp.{self._simulation_id}", json.dumps({"timestamp": current_time + simulation_start})) + self._gad_connection.send(f"goss.gridappsd.cosim.timestamp.{self._simulation_id}", + json.dumps({"timestamp": current_time + simulation_start})) #forward messages from HELICS to GOSS if self._filter_all_measurements == False: - message['output'] = self._get_helics_bus_messages(self._measurement_filter) + message['output'] = self._get_helics_bus_messages(self._measurement_filter, + pause_after_measurements) else: message['output'] = {} if self._simulation_time == self._pause_simulation_at: @@ -579,7 +607,8 @@ def run_simulation(self): if run_realtime == True: sleep_time = 1 - time.perf_counter() + begin_time_step if sleep_time < 0: - warn_message = f"Simulation {self._simulation_id} is running slower than real time!!!. Time step took {1.0 - sleep_time} seconds to execute" + warn_message = f"Simulation {self._simulation_id} is running slower than real time!!!. Time " \ + f"step took {1.0 - sleep_time} seconds to execute" log.warning(warn_message) self._gad_connection.send_simulation_status('RUNNING', warn_message, 'WARN') else: @@ -592,7 +621,8 @@ def run_simulation(self): self._simulation_time = current_time + 1 else: self._simulation_time = current_time - self._gad_connection.send(f"goss.gridappsd.cosim.timestamp.{self._simulation_id}", json.dumps({"timestamp": self._simulation_time + simulation_start})) + self._gad_connection.send(f"goss.gridappsd.cosim.timestamp.{self._simulation_id}", + json.dumps({"timestamp": self._simulation_time + simulation_start})) #forward messages from HELICS to GOSS if self._filter_all_measurements == False: message['output'] = self._get_helics_bus_messages(self._measurement_filter) @@ -608,7 +638,9 @@ def run_simulation(self): del message['output'] self._gad_connection.send(self._simulation_manager_input_topic+"."+self._simulation_id, json.dumps(message)) log.info(f'Simulation {self._simulation_id} has finished.') - self._gad_connection.send_simulation_status('COMPLETE', f'Simulation {self._simulation_id} has finished.', 'INFO') + self._gad_connection.send_simulation_status('COMPLETE', + f'Simulation {self._simulation_id} has finished.', + 'INFO') except Exception as e: message_str = f'Error in run simulation {traceback.format_exc()}' log.error(message_str) @@ -619,7 +651,9 @@ def run_simulation(self): self._close_helics_connection() finally: if self._stop_simulation: - helics.helicsFederateGlobalError(self._helics_federate, 1, "Stopping the simulation prematurely at operator's request!") + helics.helicsFederateGlobalError(self._helics_federate, + 1, + "Stopping the simulation prematurely at operator's request!") self._close_helics_connection() if targz_file: targz_file.close() @@ -676,7 +710,8 @@ def _get_gld_object_name(self, object_mrid): prefix = "" stored_object = self._object_mrid_to_name.get(object_mrid) if stored_object == None: - cim_object_dict = self._gad_connection.query_object_dictionary(model_id=self._model_mrid, object_id=object_mrid) + cim_object_dict = self._gad_connection.query_object_dictionary(model_id=self._model_mrid, + object_id=object_mrid) object_base_name = (cim_object_dict.get("data",[]))[0].get("IdentifiedObject.name","") object_type = (cim_object_dict.get("data",[]))[0].get("type","") if object_type == "LinearShuntCompensator": @@ -711,7 +746,7 @@ def _publish_to_helics_bus(self, goss_message, command_filter): ValueError() """ publish_to_helics_bus_start = time.perf_counter() - message_str = 'translating following message for HELICS simulation '+str(self._simulation_id)+' '+str(goss_message) + message_str = f'translating following message for HELICS simulation {self._simulation_id} {goss_message}' log.debug(message_str) self._gad_connection.send_simulation_status('RUNNING', message_str, 'DEBUG') if self._simulation_id == None or self._simulation_id == '' or not isinstance(self._simulation_id, str): @@ -752,12 +787,21 @@ def _publish_to_helics_bus(self, goss_message, command_filter): object_phases = (self._object_mrid_to_name.get(x.get("object",""),{})).get("phases") object_total_phases = (self._object_mrid_to_name.get(x.get("object",""),{})).get("total_phases") object_type = (self._object_mrid_to_name.get(x.get("object",""),{})).get("type") - object_name_prefix = ((self._difference_attribute_map.get(x.get("attribute",""),{})).get(object_type,{})).get("prefix") + object_name_prefix = ((self._difference_attribute_map.get(x.get("attribute", ""), + {})).get(object_type, + {})).get("prefix") cim_attribute = x.get("attribute") - object_property_list = ((self._difference_attribute_map.get(x.get("attribute",""),{})).get(object_type,{})).get("property") - phase_in_property = ((self._difference_attribute_map.get(x.get("attribute",""),{})).get(object_type,{})).get("phase_sensitive",False) + object_property_list = ((self._difference_attribute_map.get(x.get("attribute", ""), + {})).get(object_type, + {})).get("property") + phase_in_property = ((self._difference_attribute_map.get(x.get("attribute", ""), + {})).get(object_type, + {})).get("phase_sensitive", + False) if cim_attribute != "Ochre.command": - if object_name == None or object_phases == None or object_total_phases == None or object_type == None or object_name_prefix == None or cim_attribute == None or object_property_list == None: + if object_name == None or object_phases == None or object_total_phases == None \ + or object_type == None or object_name_prefix == None or cim_attribute == None \ + or object_property_list == None: parsed_result = { "object_name":object_name, "object_phases":object_phases, @@ -767,28 +811,44 @@ def _publish_to_helics_bus(self, goss_message, command_filter): "cim_attribute":cim_attribute, "object_property_list":object_property_list } - raise RuntimeError(f"Forward difference command cannot be parsed correctly one or more of attributes needed was None.\ndifference:{json.dumps(x,indent=4,sort_keys=True)}\nparsed result:{json.dumps(parsed_result,indent=4,sort_keys=True)}") + raise RuntimeError("Forward difference command cannot be parsed correctly one or more " + "of attributes needed was None.\ndifference:" + f"{json.dumps(x,indent=4,sort_keys=True)}\nparsed result:" + f"{json.dumps(parsed_result,indent=4,sort_keys=True)}") if (object_name_prefix + object_name) not in helics_input_message.keys(): helics_input_message[object_name_prefix + object_name] = {} if cim_attribute == "RegulatingControl.mode": try: val = RegulatingControlModeKind(int(x.get("value"))) except: - val = RegulatingControlModeKind[x.get("value","").replace("RegulatingControlModeKind.","",1)] + val = RegulatingControlModeKind[x.get("value", + "").replace("RegulatingControlModeKind.", + "", + 1)] if val == RegulatingControlModeKind.voltage: - helics_input_message[object_name_prefix + object_name][object_property_list[0]] = "VOLT" + helics_input_message[object_name_prefix + object_name][object_property_list[0]] = \ + "VOLT" elif val == RegulatingControlModeKind.reactivePower: - helics_input_message[object_name_prefix + object_name][object_property_list[0]] = "VAR" + helics_input_message[object_name_prefix + object_name][object_property_list[0]] = \ + "VAR" elif val == RegulatingControlModeKind.currentFlow: - helics_input_message[object_name_prefix + object_name][object_property_list[0]] = "CURRENT" + helics_input_message[object_name_prefix + object_name][object_property_list[0]] = \ + "CURRENT" else: - helics_input_message[object_name_prefix + object_name][object_property_list[0]] = "MANUAL" - log.warning(f"Unsupported capacitor control mode requested. The only supported control modes for capacitors are RegulatingControlModeKind.voltage: 0, RegulatingControlModeKind.reactivePower: 2, and RegulatingControlModeKind.currentFlow: 3.\nSetting control mode to MANUAL.\nThe invalid control mode was {x.get('value')}") - self._gad_connection.send_simulation_status("RUNNING", f"Unsupported capacitor control mode requested. The only supported control modes for capacitors are RegulatingControlModeKind.voltage: 0, RegulatingControlModeKind.reactivePower: 2, and RegulatingControlModeKind.currentFlow: 3.\nSetting control mode to MANUAL.\nThe invalid control mode was {x.get('value')}","WARN") + helics_input_message[object_name_prefix + object_name][object_property_list[0]] = \ + "MANUAL" + warnStr = "Unsupported capacitor control mode requested. The only supported " \ + "control modes for capacitors are RegulatingControlModeKind.voltage: " \ + "0, RegulatingControlModeKind.reactivePower: 2, and " \ + "RegulatingControlModeKind.currentFlow: 3.\nSetting control mode to " \ + f"MANUAL.\nThe invalid control mode was {x.get('value')}" + log.warning(warnStr) + self._gad_connection.send_simulation_status("RUNNING", warnStr, "WARN") elif cim_attribute == "RegulatingControl.enabled": val = x.get("value") if val == False: - helics_input_message[object_name_prefix + object_name][object_property_list[0]] = "MANUAL" + helics_input_message[object_name_prefix + object_name][object_property_list[0]] = \ + "MANUAL" elif cim_attribute == "RegulatingControl.targetDeadband": for y in self._difference_attribute_map[cim_attribute][object_type]["property"]: helics_input_message[object_name_prefix + object_name][y] = float(x.get("value")) @@ -816,7 +876,8 @@ def _publish_to_helics_bus(self, goss_message, command_filter): val = "OPEN" else: val = "CLOSED" - helics_input_message[object_name_prefix + object_name][object_property_list[0]] = f"{val}" + helics_input_message[object_name_prefix + object_name][object_property_list[0]] = \ + f"{val}" elif cim_attribute == "TapChanger.initialDelay": for y in object_property_list: helics_input_message[object_name_prefix + object_name][y] = float(x.get("value")) @@ -828,7 +889,8 @@ def _publish_to_helics_bus(self, goss_message, command_filter): val = "LINE_DROP_COMP" else: val = "MANUAL" - helics_input_message[object_name_prefix + object_name][object_property_list[0]] = f"{val}" + helics_input_message[object_name_prefix + object_name][object_property_list[0]] = \ + f"{val}" elif cim_attribute == "TapChanger.lineDropR": for y in object_phases: helics_input_message[object_name_prefix + object_name][object_property_list[0].format(y)] = float(x.get("value")) @@ -836,9 +898,11 @@ def _publish_to_helics_bus(self, goss_message, command_filter): for y in object_phases: helics_input_message[object_name_prefix + object_name][object_property_list[0].format(y)] = float(x.get("value")) elif cim_attribute == "PowerElectronicsConnection.p": - helics_input_message[object_name_prefix + object_name][object_property_list[0]] = float(x.get("value")) + helics_input_message[object_name_prefix + object_name][object_property_list[0]] = \ + float(x.get("value")) elif cim_attribute == "PowerElectronicsConnection.q": - helics_input_message[object_name_prefix + object_name][object_property_list[0]] = float(x.get("value")) + helics_input_message[object_name_prefix + object_name][object_property_list[0]] = \ + float(x.get("value")) elif cim_attribute == "EnergyConsumer.p": phase_count = len(object_phases) if "s1" in object_phases: @@ -853,8 +917,10 @@ def _publish_to_helics_bus(self, goss_message, command_filter): helics_input_message[object_name_prefix + object_name][object_property_list[0].format("C")] = float(x.get("value"))/phase_count else: - log.warning(f"Attribute, {cim_attribute}, is not a supported attribute in the simulator at this current time. ignoring difference.") - self._gad_connection.send_simulation_status("RUNNING", f"Attribute, {cim_attribute}, is not a supported attribute in the simulator at this current time. ignoring difference.", "WARN") + warnStr = f"Attribute, {cim_attribute}, is not a supported attribute in the " \ + "simulator at this current time. ignoring difference." + log.warning(warnStr) + self._gad_connection.send_simulation_status("RUNNING", warnStr, "WARN") else: if federate_state == 2: val = x.get("value") @@ -862,8 +928,9 @@ def _publish_to_helics_bus(self, goss_message, command_filter): default_destination = helics.helicsEndpointGetDefaultDestination(helics_input_endpoint) ochre_destination = f"{house_id}/command_input" helics.helicsEndpointSetDefaultDestination(helics_input_endpoint, ochre_destination) - log.info(f"Sending the following message to {ochre_destination}. {val}") - self._gad_connection.send_simulation_status("RUNNING", f"Sending the following message to {ochre_destination}. {val}","INFO") + infoStr = f"Sending the following message to {ochre_destination}. {val}" + log.info(infoStr) + self._gad_connection.send_simulation_status("RUNNING", infoStr,"INFO") helics_msg = helics.helicsFederateCreateMessageObject(self._helics_federate) helics.helicsMessageSetString(helics_msg, val) helics.helicsEndpointSendMessage(helics_input_endpoint, helics_msg) @@ -907,33 +974,39 @@ def _publish_to_helics_bus(self, goss_message, command_filter): if helics_input_message["external_event_handler"] == {}: del helics_input_message["external_event_handler"] goss_message_converted = json.dumps(helics_input_message, indent=4, sort_keys=True) - log.info(f"Sending the following message to the simulator. {goss_message_converted}") - self._gad_connection.send_simulation_status("RUNNING", f"Sending the following message to the simulator. {goss_message_converted}","INFO") + infoStr = f"Sending the following message to the simulator. {goss_message_converted}" + log.info(infoStr) + self._gad_connection.send_simulation_status("RUNNING", infoStr, "INFO") if federate_state == 2 and helics_input_message != {}: helics_msg = helics.helicsFederateCreateMessageObject(self._helics_federate) helics.helicsMessageSetString(helics_msg, goss_message_converted) helics.helicsEndpointSendMessage(helics_input_endpoint, helics_msg) publish_to_helics_bus_finish = time.perf_counter() publish_to_helics_profile = { - "time_between_receipt_of_message_and_processing": publish_to_helics_bus_start - test_goss_message_format.get("time_received",publish_to_helics_bus_start), + "time_between_receipt_of_message_and_processing": publish_to_helics_bus_start \ + - test_goss_message_format.get("time_received",publish_to_helics_bus_start), "time_messege_processing": publish_to_helics_bus_finish - publish_to_helics_bus_start, - "total_time": publish_to_helics_bus_finish - test_goss_message_format.get("time_received",publish_to_helics_bus_start) + "total_time": publish_to_helics_bus_finish - test_goss_message_format.get("time_received", + publish_to_helics_bus_start) } log.debug(f"Message Processing Profile: {json.dumps(publish_to_helics_profile, indent=4, sort_keys=True)}") except ValueError as ve: raise ValueError(ve) except Exception as ex: - err_msg = f"An error occured while trying to translate the update message received\n{traceback.format_exc()}" + err_msg = "An error occured while trying to translate the update message received\n" \ + f"{traceback.format_exc()}" self._gad_connection.send_simulation_status("ERROR",err_msg,"ERROR") raise RuntimeError(err_msg) - def _get_helics_bus_messages(self, measurement_filter): + def _get_helics_bus_messages(self, measurement_filter, pause_after_measurements = False): """ retrieve the measurment dictionary from the HELICS message bus Function arguments: measurement_filter -- Type: list. Description: The list of measurement id's to filter from the simulator output. + pause_after_measurements -- Type: bool. Description: boolean for automatically pausing the simulation after + publishing measurements. Function returns: helics_output -- Type: string. Description: The json structured output from the simulation. If no output was sent from the simulation then @@ -978,7 +1051,8 @@ def _get_helics_bus_messages(self, measurement_filter): helics_output = helics.helicsMessageGetString(helics_message) helics_message_source = helics.helicsMessageGetSource(helics_message) if "status" in helics_message_source: - ochre_simulation_output_topic = f"/topic/goss.gridappsd.simulation.ochre.output.{self._simulation_id}" + ochre_simulation_output_topic = "/topic/goss.gridappsd.simulation.ochre.output." \ + f"{self._simulation_id}" log.debug(f"ochre measurement message recieved at timestep {current_time}.") self._gad_connection.send(ochre_simulation_output_topic, helics_output) else: @@ -994,7 +1068,7 @@ def _get_helics_bus_messages(self, measurement_filter): objectName = x gld_properties_dict = sim_dict.get(x,None) if gld_properties_dict == None: - err_msg = "All measurements for object {} are missing from the simulator output.".format(x) + err_msg = f"All measurements for object {x} are missing from the simulator output." log.warning(err_msg) self._gad_connection.send_simulation_status('RUNNING', err_msg, 'WARN') else: @@ -1010,7 +1084,8 @@ def _get_helics_bus_messages(self, measurement_filter): propertyValue = prop_val_str objectType = conducting_equipment_type_str if prop_val_str == None: - err_msg = f"{property_name} measurement for object {x} is missing from the simulator output." + err_msg = f"{property_name} measurement for object {x} is missing from " \ + "the simulator output." log.warning(err_msg) self._gad_connection.send_simulation_status('RUNNING', err_msg, 'WARN') else: @@ -1045,7 +1120,9 @@ def _get_helics_bus_messages(self, measurement_filter): else: measurement["value"] = 1 elif conducting_equipment_type in ["PowerTransformer","TransformerTank"]: - if property_name in ["power_in_"+phases,"voltage_"+phases,"current_in_"+phases]: + if property_name in ["power_in_"+phases, + "voltage_"+phases, + "current_in_"+phases]: val = complex(val_str) (mag,ang_rad) = cmath.polar(val) ang_deg = math.degrees(ang_rad) @@ -1053,7 +1130,10 @@ def _get_helics_bus_messages(self, measurement_filter): measurement["angle"] = ang_deg else: measurement["value"] = int(val_str) - elif conducting_equipment_type in ["ACLineSegment", "EnergyConsumer","PowerElectronicsConnection","SynchronousMachine"]: + elif conducting_equipment_type in ["ACLineSegment", + "EnergyConsumer", + "PowerElectronicsConnection", + "SynchronousMachine"]: if property_name == "state_of_charge": measurement["value"] = float(val_str)*100.0 else: @@ -1062,8 +1142,12 @@ def _get_helics_bus_messages(self, measurement_filter): ang_deg = math.degrees(ang_rad) measurement["magnitude"] = mag measurement["angle"] = ang_deg - elif conducting_equipment_type in ["LoadBreakSwitch", "Recloser", "Breaker"]: - if property_name in ["power_in_"+phases,"voltage_"+phases,"current_in_"+phases]: + elif conducting_equipment_type in ["LoadBreakSwitch", + "Recloser", + "Breaker"]: + if property_name in ["power_in_"+phases, + "voltage_"+phases, + "current_in_"+phases]: val = complex(val_str) (mag,ang_rad) = cmath.polar(val) ang_deg = math.degrees(ang_rad) @@ -1075,7 +1159,9 @@ def _get_helics_bus_messages(self, measurement_filter): else: measurement["value"] = 1 elif conducting_equipment_type == "RatioTapChanger": - if property_name in ["power_in_"+phases,"voltage_"+phases,"current_in_"+phases]: + if property_name in ["power_in_"+phases, + "voltage_"+phases, + "current_in_"+phases]: val = complex(val_str) (mag,ang_rad) = cmath.polar(val) ang_deg = math.degrees(ang_rad) @@ -1084,19 +1170,29 @@ def _get_helics_bus_messages(self, measurement_filter): else: measurement["value"] = int(val_str) else: - log.warning(f"{conducting_equipment_type} is not a recognized conducting equipment type.") - self._gad_connection.send_simulation_status('RUNNING', conducting_equipment_type+" not recognized", 'WARN') - raise RuntimeError(f"{conducting_equipment_type} is not a recognized conducting equipment type.") + warnStr = f"{conducting_equipment_type} is not a recognized " \ + "conducting equipment type." + log.warning(warnStr) + self._gad_connection.send_simulation_status('RUNNING', warnStr, 'WARN') + raise RuntimeError(warnStr) # Should it raise runtime? # change to be a dictionary rather than an array cim_measurements_dict['message']["measurements"][measurement["measurement_mrid"]] = measurement cim_output = cim_measurements_dict log.debug(f"measurement message recieved at timestep {current_time}.") - self._gad_connection.send(topics.simulation_output_topic(self._simulation_id), json.dumps(cim_output, indent=4, sort_keys=True)) - log.debug(f"Message from simulation processing time: {time.perf_counter() - get_helics_bus_messages_start}.") + self._gad_connection.send(topics.simulation_output_topic(self._simulation_id), + json.dumps(cim_output, indent=4, sort_keys=True)) + if pause_after_measurements: + self._pause_simulation = True + debugStr = "Simulation paused automatically after publishing measurements." + log.debug(debugStr) + self._gad_connection.send_simulation_status('PAUSED', debugStr, 'INFO') + log.debug("Message from simulation processing time: " + f"{time.perf_counter() - get_helics_bus_messages_start}.") return {} except ValueError as ve: - raise RuntimeError(f"{str(ve)}.\nObject Name: {objectName}\nObject Type: {objectType}\nProperty Name: {propertyName}\n Property Value{propertyValue}") + raise RuntimeError(f"{str(ve)}.\nObject Name: {objectName}\nObject Type: {objectType}\nProperty Name: " + f"{propertyName}\n Property Value{propertyValue}") except Exception as e: message_str = f'Error on get HELICS Bus Messages for {self._simulation_id} {traceback.format_exc()}' log.error(message_str) @@ -1179,8 +1275,11 @@ def _create_cim_object_map(self,map_file=None): object_name = conducting_equipment_name; property_name = "voltage_" + phases; else: - raise RuntimeError(f"_create_cim_object_map: The value of measurement_type is not a valid type.\nValid types for LinearShuntCompensators are VA, Pos, and PNV.\nmeasurement_type = {measurement_type}.") - elif "PowerTransformer" in conducting_equipment_type or "TransformerTank" in conducting_equipment_type: + raise RuntimeError("_create_cim_object_map: The value of measurement_type is not a valid " + "type.\nValid types for LinearShuntCompensators are VA, Pos, and PNV.\n" + f"measurement_type = {measurement_type}.") + elif "PowerTransformer" in conducting_equipment_type \ + or "TransformerTank" in conducting_equipment_type: if measurement_type == "VA": object_name = conducting_equipment_name; property_name = "power_in_" + phases; @@ -1191,7 +1290,9 @@ def _create_cim_object_map(self,map_file=None): object_name = conducting_equipment_name; property_name = "current_in_" + phases; else: - raise RuntimeError(f"_create_cim_object_map: The value of measurement_type is not a valid type.\nValid types for PowerTransformer and TransformerTank are VA, PNV, and A.\nmeasurement_type = {measurement_type}.") + raise RuntimeError("_create_cim_object_map: The value of measurement_type is not a valid " + "type.\nValid types for PowerTransformer and TransformerTank are VA, " + f"PNV, and A.\nmeasurement_type = {measurement_type}.") elif "RatioTapChanger" in conducting_equipment_type: if measurement_type == "VA": object_name = conducting_equipment_name; @@ -1206,7 +1307,9 @@ def _create_cim_object_map(self,map_file=None): object_name = conducting_equipment_name; property_name = "current_in_" + phases; else: - raise RuntimeError(f"_create_cim_object_map: The value of measurement_type is not a valid type.\nValid types for RatioTapChanger are VA, PNV, Pos, and A.\nmeasurement_type = {measurement_type}.") + raise RuntimeError("_create_cim_object_map: The value of measurement_type is not a valid " + "type.\nValid types for RatioTapChanger are VA, PNV, Pos, and A.\n" + f"measurement_type = {measurement_type}.") elif "ACLineSegment" in conducting_equipment_type: if measurement_type == "VA": object_name = conducting_equipment_name; @@ -1228,8 +1331,12 @@ def _create_cim_object_map(self,map_file=None): else: property_name = "current_in_" + phases else: - raise RuntimeError(f"_create_cim_object_map: The value of measurement_type is not a valid type.\nValid types for ACLineSegment are VA, PNV, and A.\nmeasurement_type = {measurement_type}.") - elif "LoadBreakSwitch" in conducting_equipment_type or "Recloser" in conducting_equipment_type or "Breaker" in conducting_equipment_type: + raise RuntimeError("_create_cim_object_map: The value of measurement_type is not a valid " + "type.\nValid types for ACLineSegment are VA, PNV, and A.\n" + f"measurement_type = {measurement_type}.") + elif "LoadBreakSwitch" in conducting_equipment_type \ + or "Recloser" in conducting_equipment_type \ + or "Breaker" in conducting_equipment_type: if measurement_type == "VA": object_name = conducting_equipment_name; property_name = "power_in_" + phases; @@ -1243,7 +1350,9 @@ def _create_cim_object_map(self,map_file=None): object_name = conducting_equipment_name; property_name = "current_in_" + phases; else: - raise RuntimeError(f"_create_cim_object_map: The value of measurement_type is not a valid type.\nValid types for LoadBreakSwitch are VA, PNV, and A.\nmeasurement_type = {measurement_type}.") + raise RuntimeError("_create_cim_object_map: The value of measurement_type is not a valid " + "type.\nValid types for LoadBreakSwitch are VA, PNV, and A.\n" + f"measurement_type = {measurement_type}.") elif "EnergyConsumer" in conducting_equipment_type: if measurement_type == "VA": object_name = conducting_equipment_name; @@ -1258,7 +1367,9 @@ def _create_cim_object_map(self,map_file=None): object_name = connectivity_node; property_name = "measured_current_" + phases; else: - raise RuntimeError(f"_create_cim_object_map: The value of measurement_type is not a valid type.\nValid types for EnergyConsumer are VA, A, and PNV.\nmeasurement_type = {measurement_type}.") + raise RuntimeError("_create_cim_object_map: The value of measurement_type is not a valid " + "type.\nValid types for EnergyConsumer are VA, A, and PNV.\n" + f"measurement_type = {measurement_type}.") elif "PowerElectronicsConnection" in conducting_equipment_type: if measurement_type == "VA": object_name = conducting_equipment_name; @@ -1276,7 +1387,9 @@ def _create_cim_object_map(self,map_file=None): object_name = conducting_equipment_name property_name = "state_of_charge" else: - raise RuntimeError("_create_cim_object_map: The value of measurement_type is not a valid type.\nValid types for PowerElectronicsConnection are VA, A, SoC, and PNV.\nmeasurement_type = %s.".format(measurement_type)) + raise RuntimeError("_create_cim_object_map: The value of measurement_type is not a valid " + "type.\nValid types for PowerElectronicsConnection are VA, A, SoC, and " + f"PNV.\nmeasurement_type = {measurement_type}") elif "SynchronousMachine" in conducting_equipment_type: if measurement_type == "VA": object_name = conducting_equipment_name; @@ -1288,9 +1401,15 @@ def _create_cim_object_map(self,map_file=None): object_name = connectivity_node; property_name = "measured_current_" + phases; else: - raise RuntimeError(f"_create_cim_object_map: The value of measurement_type is not a valid type.\nValid types for SynchronousMachine are VA, A, and PNV.\nmeasurement_type = {measurement_type}.") + raise RuntimeError("_create_cim_object_map: The value of measurement_type is not a valid " + "type.\nValid types for SynchronousMachine are VA, A, and PNV.\n" + f"measurement_type = {measurement_type}.") else: - raise RuntimeError(f"_create_cim_object_map: The value of conducting_equipment_type is not a valid type.\nValid types for conducting_equipment_type are ACLineSegment, LinearShuntCompesator, LoadBreakSwitch, PowerElectronicsConnection, EnergyConsumer, RatioTapChanger, and PowerTransformer.\nconducting_equipment_type = {conducting_equipment_type}.") + raise RuntimeError("_create_cim_object_map: The value of conducting_equipment_type is not a " + "valid type.\nValid types for conducting_equipment_type are ACLineSegment, " + "LinearShuntCompesator, LoadBreakSwitch, PowerElectronicsConnection, " + "EnergyConsumer, RatioTapChanger, and PowerTransformer.\n" + f"conducting_equipment_type = {conducting_equipment_type}.") property_dict = { "property" : property_name, @@ -1378,13 +1497,15 @@ def _create_cim_object_map(self,map_file=None): "total_phases" : y.get("phases"), "prefix" : "ld_" } - if "s1" in self._object_mrid_to_name[y.get("mRID")]["phases"] or "s2" in self._object_mrid_to_name[y.get("mRID")]["phases"]: + if "s1" in self._object_mrid_to_name[y.get("mRID")]["phases"] \ + or "s2" in self._object_mrid_to_name[y.get("mRID")]["phases"]: self._object_mrid_to_name[y.get("mRID")]["type"] = "triplex_load" else: self._object_mrid_to_name[y.get("mRID")]["type"] = "load" except Exception as e: - log.error(f"The measurement map file, {map_file}, couldn't be translated.\nError:{traceback.format_exc()}") - self._gad_connection.send_simulation_status('STARTED', f"The measurement map file, {map_file}, couldn't be translated.\nError:{traceback.format_exc()}", 'ERROR') + errStr = f"The measurement map file, {map_file}, couldn't be translated.\nError:{traceback.format_exc()}" + log.error(errStr) + self._gad_connection.send_simulation_status('STARTED', errStr, 'ERROR') def _main(simulation_id, broker_port, simulation_request): From c33fb1c85950dca0a552b186723d4771e42874a7 Mon Sep 17 00:00:00 2001 From: afisher1 <4552674+afisher1@users.noreply.github.com> Date: Tue, 9 Apr 2024 09:46:12 -0700 Subject: [PATCH 08/14] removing unused variable in helics_goss_bridge --- services/helicsgossbridge/service/helics_goss_bridge.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/services/helicsgossbridge/service/helics_goss_bridge.py b/services/helicsgossbridge/service/helics_goss_bridge.py index 2ee06ccc9..c9e48208b 100644 --- a/services/helicsgossbridge/service/helics_goss_bridge.py +++ b/services/helicsgossbridge/service/helics_goss_bridge.py @@ -794,10 +794,6 @@ def _publish_to_helics_bus(self, goss_message, command_filter): object_property_list = ((self._difference_attribute_map.get(x.get("attribute", ""), {})).get(object_type, {})).get("property") - phase_in_property = ((self._difference_attribute_map.get(x.get("attribute", ""), - {})).get(object_type, - {})).get("phase_sensitive", - False) if cim_attribute != "Ochre.command": if object_name == None or object_phases == None or object_total_phases == None \ or object_type == None or object_name_prefix == None or cim_attribute == None \ From b99f5c545046ec2d7d713b3fc53e8007e971e55d Mon Sep 17 00:00:00 2001 From: poorva1209 Date: Thu, 11 Apr 2024 09:12:32 -0700 Subject: [PATCH 09/14] Returning valid json if response data is not valid json like glm or dss --- .../gov/pnnl/goss/gridappsd/process/ProcessEvent.java | 11 +++++++++++ .../{ => helicsgossbridge}/context_manager.config | 0 2 files changed, 11 insertions(+) rename services/{ => helicsgossbridge}/context_manager.config (100%) diff --git a/gov.pnnl.goss.gridappsd/src/gov/pnnl/goss/gridappsd/process/ProcessEvent.java b/gov.pnnl.goss.gridappsd/src/gov/pnnl/goss/gridappsd/process/ProcessEvent.java index 0e6e8f1c5..f87147f91 100644 --- a/gov.pnnl.goss.gridappsd/src/gov/pnnl/goss/gridappsd/process/ProcessEvent.java +++ b/gov.pnnl.goss.gridappsd/src/gov/pnnl/goss/gridappsd/process/ProcessEvent.java @@ -77,6 +77,9 @@ import javax.jms.Destination; +import org.codehaus.jettison.json.JSONException; +import org.codehaus.jettison.json.JSONObject; + import pnnl.goss.core.Client; import pnnl.goss.core.DataError; import pnnl.goss.core.DataResponse; @@ -284,6 +287,7 @@ public void onMessage(Serializable message) { } ConfigurationRequest configRequest = null; + System.out.println("*******************"+request.toString()); if(request instanceof ConfigurationRequest){ configRequest = ((ConfigurationRequest)request); } else{ @@ -383,6 +387,13 @@ private void sendData(Client client, Destination replyDestination, Serializable } if(responseFormat == null || responseFormat.equals("JSON")) { + try{ + new JSONObject(data.toString()); + } + catch(JSONException e){ + data = data.toString().replace("\"", "\\\""); + data = "\""+data+"\""; + } String r = "{\"data\":"+data+",\"responseComplete\":true,\"id\":\""+processId+"\"}"; client.publish(replyDestination, r); } diff --git a/services/context_manager.config b/services/helicsgossbridge/context_manager.config similarity index 100% rename from services/context_manager.config rename to services/helicsgossbridge/context_manager.config From c9e0581f093579560001c2202226684ffd9b4a3a Mon Sep 17 00:00:00 2001 From: poorva1209 Date: Thu, 11 Apr 2024 09:17:44 -0700 Subject: [PATCH 10/14] Returning valid json if response data is not valid json like glm or dss --- .../src/gov/pnnl/goss/gridappsd/process/ProcessEvent.java | 1 - 1 file changed, 1 deletion(-) diff --git a/gov.pnnl.goss.gridappsd/src/gov/pnnl/goss/gridappsd/process/ProcessEvent.java b/gov.pnnl.goss.gridappsd/src/gov/pnnl/goss/gridappsd/process/ProcessEvent.java index f87147f91..cae5664d0 100644 --- a/gov.pnnl.goss.gridappsd/src/gov/pnnl/goss/gridappsd/process/ProcessEvent.java +++ b/gov.pnnl.goss.gridappsd/src/gov/pnnl/goss/gridappsd/process/ProcessEvent.java @@ -287,7 +287,6 @@ public void onMessage(Serializable message) { } ConfigurationRequest configRequest = null; - System.out.println("*******************"+request.toString()); if(request instanceof ConfigurationRequest){ configRequest = ((ConfigurationRequest)request); } else{ From d8aee9cc33d52b712891edf922f861e2d992ad23 Mon Sep 17 00:00:00 2001 From: poorva1209 Date: Thu, 11 Apr 2024 09:19:44 -0700 Subject: [PATCH 11/14] Returning valid json if response data is not valid json like glm or dss --- services/{helicsgossbridge => }/context_manager.config | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename services/{helicsgossbridge => }/context_manager.config (100%) diff --git a/services/helicsgossbridge/context_manager.config b/services/context_manager.config similarity index 100% rename from services/helicsgossbridge/context_manager.config rename to services/context_manager.config From 7f93749464f6d06a642668581bbea50484e4d3ff Mon Sep 17 00:00:00 2001 From: poorva1209 Date: Thu, 2 May 2024 15:26:10 -0700 Subject: [PATCH 12/14] added field_model_mrid to service start --- .../goss/gridappsd/service/ServiceManagerImpl.java | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/gov.pnnl.goss.gridappsd/src/gov/pnnl/goss/gridappsd/service/ServiceManagerImpl.java b/gov.pnnl.goss.gridappsd/src/gov/pnnl/goss/gridappsd/service/ServiceManagerImpl.java index 53812beef..da6a66d7a 100755 --- a/gov.pnnl.goss.gridappsd/src/gov/pnnl/goss/gridappsd/service/ServiceManagerImpl.java +++ b/gov.pnnl.goss.gridappsd/src/gov/pnnl/goss/gridappsd/service/ServiceManagerImpl.java @@ -316,6 +316,11 @@ public String startServiceForSimultion(String serviceId, HashMap } } } + else{ + if(staticArg.contains("(field_model_mrid")){ + staticArg = staticArg.replace("(field_model_mrid)",this.getFieldModelMrid()); + } + } commands.add(staticArg); } } @@ -484,6 +489,15 @@ public void run() { }.start(); } + public String getFieldModelMrid() { + if (this.configurationProperties != null) { + Object value = this.configurationProperties.get("field.model.mrid"); + if (value != null) + return value.toString(); + } + return null; + } + From ebb89a412c836103b2ecd8f3da7c23c7f2b9b37e Mon Sep 17 00:00:00 2001 From: Sharma Date: Thu, 9 May 2024 10:35:39 -0700 Subject: [PATCH 13/14] added distrbuted static y bus --- Dockerfile | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Dockerfile b/Dockerfile index 729b1abb1..09fc84796 100644 --- a/Dockerfile +++ b/Dockerfile @@ -78,6 +78,18 @@ RUN mkdir ${TEMP_DIR} \ && cp /gridappsd/services/gridappsd-toolbox/dynamic-ybus/gridappsd-dynamic-ybus-service.config /gridappsd/services/ \ && cd \ && rm -rf ${TEMP_DIR} + +# Get the gridapspd-distributed-ybus-service from the proper repository +RUN mkdir ${TEMP_DIR} \ + && cd ${TEMP_DIR} \ + && git clone https://github.com/GRIDAPPSD/gridappsd-distributed-static-ybus-service.git -b main \ + && cd gridappsd-distributed-static-ybus-service \ + && mkdir -p /gridappsd/services/gridappsd-distributed-static-ybus-service \ + && rm .git -rf \ + && cp -r * /gridappsd/services/gridappsd-distributed-static-ybus-service \ + && cp /gridappsd/services/gridappsd-distributed-static-ybus-service/gridappsd-distributed-static-ybus-service.config /gridappsd/services/ \ + && cd \ + && rm -rf ${TEMP_DIR} # Copy initial applications and services into the container. # From ac9984600de3171d072d47b370ce4e1381745972 Mon Sep 17 00:00:00 2001 From: poorva1209 Date: Mon, 13 May 2024 14:53:45 -0700 Subject: [PATCH 14/14] Update ServiceManagerImpl.java --- .../gov/pnnl/goss/gridappsd/service/ServiceManagerImpl.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gov.pnnl.goss.gridappsd/src/gov/pnnl/goss/gridappsd/service/ServiceManagerImpl.java b/gov.pnnl.goss.gridappsd/src/gov/pnnl/goss/gridappsd/service/ServiceManagerImpl.java index da6a66d7a..16cd1205f 100755 --- a/gov.pnnl.goss.gridappsd/src/gov/pnnl/goss/gridappsd/service/ServiceManagerImpl.java +++ b/gov.pnnl.goss.gridappsd/src/gov/pnnl/goss/gridappsd/service/ServiceManagerImpl.java @@ -318,8 +318,8 @@ public String startServiceForSimultion(String serviceId, HashMap } else{ if(staticArg.contains("(field_model_mrid")){ - staticArg = staticArg.replace("(field_model_mrid)",this.getFieldModelMrid()); - } + staticArg = staticArg.replace("(field_model_mrid)",this.getFieldModelMrid()); + } } commands.add(staticArg); }