def __init__(self, gapps, simulation_id, Rids): self.gapps = gapps self.simulation_id = simulation_id self.Rids = Rids self.rid_idx = 0 self.keepLoopingFlag = True self.publish_to_topic = simulation_input_topic(simulation_id)
def __init__(self, simulation_id, gridappsd_obj, ACline, obj_msr_loadsw): """ Create a ``CapacitorToggler`` object This object should be used as a subscription callback from a ``GridAPPSD`` object. This class will toggle the capacitors passed to the constructor off and on every five messages that are received on the ``fncs_output_topic``. Note ---- This class does not subscribe only publishes. Parameters ---------- simulation_id: str The simulation_id to use for publishing to a topic. gridappsd_obj: GridAPPSD An instatiated object that is connected to the gridappsd message bus usually this should be the same object which subscribes, but that isn't required. """ self._gapps = gridappsd_obj self._simulation_id = simulation_id self._ACline = ACline self._obj_msr_loadsw = obj_msr_loadsw self._message_count = 0 self._last_toggle_on = False self._open_diff = DifferenceBuilder(simulation_id) self._close_diff = DifferenceBuilder(simulation_id) self._publish_to_topic = simulation_input_topic(simulation_id) self._flag = 0 self._start_time = 0 _log.info("Building cappacitor list")
def test_listener_multi_topic(gridappsd_client): gappsd = gridappsd_client class Listener: def __init__(self): self.call_count = 0 def reset(self): self.call_count = 0 def on_message(self, headers, message): print("Message was: {}".format(message)) self.call_count += 1 listener = Listener() input_topic = t.simulation_input_topic("5144") output_topic = t.simulation_output_topic("5144") gappsd.subscribe(input_topic, listener) gappsd.subscribe(output_topic, listener) gappsd.send(input_topic, "Any message") sleep(1) assert 1 == listener.call_count listener.reset() gappsd.send(output_topic, "No big deal") sleep(1) assert 1 == listener.call_count
def send_command(msg): goss = GOSS() goss.connect() # print(json.dumps(msg,indent=2)) request = json.dumps(msg) status = goss.send(simulation_input_topic(simulation_id), request) print(status)
def test_alarm_output(sim_config_file, sim_result_file): simulation_id = None sim_config_file = os.path.join( os.path.dirname(__file__), f"simulation_config_files/{sim_config_file}") sim_result_file = os.path.join( os.path.dirname(__file__), f"simulation_baseline_files/{sim_result_file}") assert os.path.exists( sim_config_file ), f"File {sim_config_file} must exist to run simulation test" with startup_containers(): with gappsd() as gapps: os.makedirs("/tmp/output", exist_ok=True) with open("/tmp/output/simulation.output", 'w') as outfile: sim_complete = False rcvd_measurement = False def onmeasurement(sim, timestep, measurements): nonlocal rcvd_measurement # if not rcvd_measurement: rcvd_measurement = True LOGGER.info('A measurement happened at %s', timestep) def onfinishsimulation(sim): nonlocal sim_complete sim_complete = True print("Completed simulator") with open(sim_config_file) as fp: run_config = json.load(fp) print(run_config["simulation_config"]["start_time"]) sim = Simulation(gapps, run_config) LOGGER.info('Starting the simulation') sim.add_onmesurement_callback(onmeasurement) sim.add_oncomplete_callback(onfinishsimulation) LOGGER.info('sim.add_onmesurement_callback') LOGGER.info("Querying Alarm topic for alarms") sim.start_simulation() print(sim.simulation_id) alarms_topic = t.service_output_topic('gridappsd-alarms', sim.simulation_id) log_topic = t.simulation_output_topic(sim.simulation_id) input_topic = t.simulation_input_topic(sim.simulation_id) gapps.subscribe(alarms_topic, on_message) gapps.subscribe(log_topic, on_message) # gapps.subscribe(input_topic, on_message) while not sim_complete: LOGGER.info('Sleeping') sleep(30)
def __init__(self, simulation_id, gridappsd_obj, reg_list, cap_list, demand, line, xfmr, msr_mrids_demand, msr_mrids_cap, msr_mrids_reg, obj_msr_loadsw, switches, obj_msr_inv, obj_msr_node): """ Create a ``CapacitorToggler`` object This object should be used as a subscription callback from a ``GridAPPSD`` object. This class will toggle the capacitors passed to the constructor off and on every five messages that are received on the ``fncs_output_topic``. Note ---- This class does not subscribe only publishes. Parameters ---------- simulation_id: str The simulation_id to use for publishing to a topic. gridappsd_obj: GridAPPSD An instatiated object that is connected to the gridappsd message bus usually this should be the same object which subscribes, but that isn't required. capacitor_list: list(str) A list of capacitors mrids to turn on/off """ self._gapps = gridappsd_obj self._flag = 0 self.reg_list = reg_list self._cap_list = cap_list self._store = [] self._message_count = 0 self._last_toggle_on = False self._cap_open_diff = DifferenceBuilder(simulation_id) self._cap_close_diff = DifferenceBuilder(simulation_id) self._tap_open_diff = DifferenceBuilder(simulation_id) self._tap_close_diff = DifferenceBuilder(simulation_id) self._publish_to_topic = simulation_input_topic(simulation_id) self._pv_qpower = DifferenceBuilder(simulation_id) self.msr_mrids_loadsw = obj_msr_loadsw self.msr_mrids_demand = msr_mrids_demand self.msr_mrids_cap = msr_mrids_cap self.msr_mrids_reg = msr_mrids_reg self.LineData = line self.DemandData = demand self.xfmr = xfmr self.obj_msr_inv = obj_msr_inv self.obj_msr_node = obj_msr_node # self.Inverter_PnS = Inverter_PnS # self.obj_msr_sync = obj_msr_sync self.TOP = [] self.switches = switches self.flag = 0 _log.info("Building cappacitor list")
def __init__(self, simulation_id, gridappsd_obj, ACline, obj_msr_loadsw, obj_msr_reg, switches, regulators): """ Create a ``CapacitorToggler`` object This object should be used as a subscription callback from a ``GridAPPSD`` object. This class will toggle the capacitors passed to the constructor off and on every five messages that are received on the ``fncs_output_topic``. The five message mentioned above refers to DEFAULT_MESSAGE_PERIOD Note ---- This class does not subscribe only publishes. Parameters ---------- simulation_id: str The simulation_id to use for publishing to a topic. gridappsd_obj: GridAPPSD An instatiated object that is connected to the gridappsd message bus usually this should be the same object which subscribes, but that isn't required. capacitor_list: list(str) A list of capacitors mrids to turn on/off """ self._gapps = gridappsd_obj # the five variables below are different than the ones presented on original file # have been created by Shiva to see AC lines and switch self._simulation_id = simulation_id self._ACline = ACline self._obj_msr_loadsw = obj_msr_loadsw self._obj_msr_reg = obj_msr_reg self._flag = 0 self._start_time = 0 self.check = True self.inp = False self._switches = switches self._regulators = regulators self._message_count = 0 self._last_toggle_on = False self._open_diff = DifferenceBuilder(simulation_id) self._close_diff = DifferenceBuilder(simulation_id) self._tap_close_diff = DifferenceBuilder(simulation_id) self._publish_to_topic = simulation_input_topic(simulation_id) _log.info("Building capacitor list")
def _main(): global sim_id, gapps if len(sys.argv) < 3 or '-help' in sys.argv: usestr = '\nUsage: ' + sys.argv[ 0] + ' simulation_id tap|reg|cap|switch\n' usestr += ''' Optional command line arguments: -help: show this usage message ''' print(usestr, file=sys.stderr, flush=True) exit() gapps = GridAPPSD() sim_id = sys.argv[1] diff = DifferenceBuilder(sim_id) # hardwired for 13assets if sys.argv[2] == 'tap' or sys.argv[2] == 'reg': reg_id = '_A480E0A9-AD2B-4D8E-9478-71C29F738221' # node RG60.2 diff.add_difference(reg_id, 'TapChanger.step', 5, 8) elif sys.argv[2] == 'cap': cap_id = '_28456F60-7196-47E4-9BE6-54F7EAABC04A' # bus 611 diff.add_difference(cap_id, 'ShuntCompensator.sections', 0, 1) else: switch_id = '_4E1B3F09-CB88-4A5E-8198-24490EE7FC58' # between bus 671-692 diff.add_difference(switch_id, 'Switch.open', 1, 0) msg = diff.get_message() print(json.dumps(msg)) publish_to_topic = simulation_input_topic(sim_id) gapps.send(publish_to_topic, json.dumps(msg)) time.sleep(2) gapps.disconnect()
def callback(headers, message): global end_program, flag, w, log_timestamps log_timestamp = [] publish_to_topic = simulation_input_topic(simulation_id) if type(message) == str: message = json.loads(message) if 'message' not in message: if message['processStatus'] == 'COMPLETE' or \ message['processStatus']=='CLOSED': print('The End') end_program = True else: #Uncomment for troubleshooting print(message) ''' Only runs the first output query. Grabs the keys from the message, looks them up for their real names, and writes the header with the real names while still using the mrids as headers for dictwriter purposes. ''' if flag == 0: header_mrids = message['message']['measurements'].keys() header_names = [] print(header_mrids) for i in header_mrids: lookup_mrid = next(item for item in meas_object_list if item['measid'] == i) lookup_name = lookup_mrid['name'] header_names.append(lookup_name) w = csv.DictWriter(f, header_mrids) print(header_names) header_names_dict = dict(zip(list(header_mrids), header_names)) w.writerow(header_names_dict) flag = 1 else: pass print(type(message)) w.writerow(message['message']['measurements']) log_timestamps.append(SIMULATION_TIME)
def __init__(self, simulation_id, gridappsd_obj, capacitor_list): """ Create a ``CapacitorToggler`` object This object should be used as a subscription callback from a ``GridAPPSD`` object. This class will toggle the capacitors passed to the constructor off and on every five messages that are received on the ``fncs_output_topic``. Note ---- This class does not subscribe only publishes. Parameters ---------- simulation_id: str The simulation_id to use for publishing to a topic. gridappsd_obj: GridAPPSD An instatiated object that is connected to the gridappsd message bus usually this should be the same object which subscribes, but that isn't required. capacitor_list: list(str) A list of capacitors mrids to turn on/off """ self._gapps = gridappsd_obj self._cap_list = capacitor_list self._message_count = 0 self._last_toggle_on = False self._open_diff = DifferenceBuilder(simulation_id) self._close_diff = DifferenceBuilder(simulation_id) self._publish_to_topic = simulation_input_topic(simulation_id) _log.info("Building cappacitor list") for cap_mrid in capacitor_list: _log.debug(f"Adding cap sum difference to list: {cap_mrid}") self._open_diff.add_difference(cap_mrid, "ShuntCompensator.sections", 0, 1) self._close_diff.add_difference(cap_mrid, "ShuntCompensator.sections", 1, 0)
def __init__(self, simulation_id, gridappsd_obj, model_mrid, start_time, app_config={}): """ Create a ``Solar_Forecast`` object Note ---- This class does not subscribe only publishes. Parameters ---------- simulation_id: str The simulation_id to use for publishing to a topic. gridappsd_obj: GridAPPSD An instatiated object that is connected to the gridappsd message bus usually this should be the same object which subscribes, but that isn't required. """ _log.info("Init application") self.simulation_id = simulation_id self._gapps = gridappsd_obj self.fidselect = model_mrid self._publish_to_topic = simulation_input_topic(simulation_id) self._start_time = start_time self._end_time = start_time + 3600 * 24 self._message_count = 0 self._run_freq = app_config.get('run_freq', 30) self._run_realtime = app_config.get('run_realtime', True) self._port = '9002' print(self._port ) self._weather_df = None # self._weather_df = query_weather.query_weather(self._start_time,self._end_time) self.resFolder = "" MainDir="" circuit_name = "" self.resFolder = os.path.join(MainDir, 'adms_result_' + circuit_name + '_' + str(self._start_time)) self._result_csv = ResultCSV() self._result_csv.create_result_folder(self.resFolder) self._result_csv.create_result_file(self.resFolder, 'result.csv', 'second,epoch time,GHI,forecast time,Forecast GHI') # self.create_result_file(self.resFolder) # self._results, self._res_csvfile, self._results_writer = self.create_result_file(self.resFolder, 'second,epoch time,GHI,forecast time,Forecast GHI') ctx = zmq.Context() self._skt = ctx.socket(zmq.PUB) if running_on_host(): self._skt.bind('tcp://127.0.0.1:{}'.format(self._port)) else: self._skt.bind('tcp://*:{}'.format(self._port)) time.sleep(.3) signal.signal(signal.SIGTERM, self.signal_handler) signal.signal(signal.SIGINT, self.signal_handler) obj = dict(first=dict(first=1, time=1)) jobj = json.dumps(obj).encode('utf8') zobj = zlib.compress(jobj) print('zipped pickle is %i bytes' % len(zobj)) self._skt.send(zobj)
def send_command(self, object_ids, attributes, forward_values, reverse_values, sim_id=None): """Function for sending a command into a running simulation. This is partly a wrapper to DifferenceBuilder, but also sends the command into the simulation. Note all list parameters below must be 1:1. In other words, object_ids[3] should correspond to attributes[3], etc. :param object_ids: List of mrids of objects to command. :param attributes: List of CIM attributes belonging to the objects. These attributes are what we're actually commanding/changing. :param forward_values: List of new values for attributes. :param reverse_values: List of old (current) values for attributes. :param sim_id: Simulation ID. If None, will attempt to use self.sim.simulation_id. If that is also None, ValueError will be raised. :returns: Dictionary representing the message that gets sent in. If no message will be sent (if input lists are empty), returns None instead. """ # Ensure we get lists. if ((not isinstance(object_ids, list)) or (not isinstance(attributes, list)) or (not isinstance(forward_values, list)) or (not isinstance(reverse_values, list))): m = 'object_ids, attributes, forward_values, and reverse_values '\ 'must all be lists!' raise TypeError(m) # Ensure lists are the same length. if not (len(object_ids) == len(attributes) == len(forward_values) == len(reverse_values)): m = 'object_ids, attributes, forward_values, and reverse_values '\ 'must be the same length!' raise ValueError(m) # Don't bother continuing if the lists are empty. if len(object_ids) == 0: self.log.info('send_command given empty lists, returning None.') return None # Ensure we have a simulation ID. if sim_id is None: try: sim_id = self.sim.simulation_id except AttributeError: m = ('sim_id input is None, and so is self.sim.simulation_id. ' 'In order to send a command, we must have a sim_id.') raise ValueError(m) from None self.log.debug('Input checks complete for send_command.') # Initialize difference builder. diff_builder = DiffBuilder(simulation_id=sim_id) self.log.debug('DifferenceBuilder initialized.') # Iterate to build add differences. for k in range(len(object_ids)): diff_builder.add_difference(object_id=object_ids[k], attribute=attributes[k], forward_value=forward_values[k], reverse_value=reverse_values[k]) # Get the message and log it. msg = diff_builder.get_message() msg_str = json.dumps(msg) self.log.info('Preparing to send following command: {}' .format(msg_str)) # Send command to simulation. self.gad.send(topic=topics.simulation_input_topic(sim_id), message=msg_str) # Return the message in case we want to examine it, audit, etc. # Mainly useful for testing at this point. return msg
def _main(): parser = argparse.ArgumentParser() parser.add_argument("simulation_id", help="Simulation id to use for responses on the message bus.") parser.add_argument("request", help="Simulation Request") # These are now set through the docker container interface via env variables or defaulted to # proper values. # # parser.add_argument("-u", "--user", default="system", # help="The username to authenticate with the message bus.") # parser.add_argument("-p", "--password", default="manager", # help="The password to authenticate with the message bus.") # parser.add_argument("-a", "--address", default="127.0.0.1", # help="tcp address of the mesage bus.") # parser.add_argument("--port", default=61613, type=int, # help="the stomp port on the message bus.") # opts = parser.parse_args() sim_output_topic = simulation_output_topic(opts.simulation_id) sim_input_topic = simulation_input_topic(opts.simulation_id) sim_request = json.loads(opts.request.replace("\'","")) model_mrid = sim_request["power_system_config"]["Line_name"] gapps = GridAPPSD(opts.simulation_id, address=utils.get_gridappsd_address(), username=utils.get_gridappsd_user(), password=utils.get_gridappsd_pass()) capacitors_dict = {} switches_dict = {} capacitors_meas_dict = {} switches_meas_dict = {} request = { "modelId": model_mrid, "requestType": "QUERY_OBJECT_DICT", "resultFormat": "JSON", "objectType": "LinearShuntCompensator" } response = gapps.get_response("goss.gridappsd.process.request.data.powergridmodel",request) for capacitor in response["data"]: capacitors_dict[capacitor["id"]] = capacitor request = { "modelId": model_mrid, "requestType": "QUERY_OBJECT_DICT", "resultFormat": "JSON", "objectType": "LoadBreakSwitch" } response = gapps.get_response("goss.gridappsd.process.request.data.powergridmodel",request) for switch in response["data"]: switches_dict[switch["id"]] = switch #print(capacitors_dict) #print(switches_dict) request = {"modelId": model_mrid, "requestType": "QUERY_OBJECT_MEASUREMENTS", "resultFormat": "JSON", "objectType": "LinearShuntCompensator" } response = gapps.get_response("goss.gridappsd.process.request.data.powergridmodel",request) for measurement in response["data"]: capacitors_meas_dict[measurement["measid"]] = measurement request = {"modelId": model_mrid, "requestType": "QUERY_OBJECT_MEASUREMENTS", "resultFormat": "JSON", "objectType": "LoadBreakSwitch" } response = gapps.get_response("goss.gridappsd.process.request.data.powergridmodel",request) for measurement in response["data"]: switches_meas_dict[measurement["measid"]] = measurement #print(capacitors_meas_dict) #print(switches_meas_dict) #capacitors_dict = get_capacitor_measurements(gapps, model_mrid) #switches_dict = get_switch_measurements(gapps, model_mrid) subscriber = SimulationSubscriber(opts.simulation_id, gapps, capacitors_dict, switches_dict, capacitors_meas_dict, switches_meas_dict) gapps.subscribe(sim_input_topic, subscriber) gapps.subscribe(sim_output_topic, subscriber) while True: time.sleep(0.1)