예제 #1
0
def reg_msg(name, fv=1, rv=0):
    if name not in reg_name_map:
        print('No regulator named ' + name)
        return None
    _diff = DifferenceBuilder(simulation_id)
    _diff.add_difference(reg_name_map[name]['id'], "TapChanger.step", fv, rv)
    msg = _diff.get_message()
    return msg
예제 #2
0
def switch_msg(name, fv=1, rv=0):
    if name not in switch_name_map:
        print('No switch named ' + name)
        return None
    _diff = DifferenceBuilder(simulation_id)
    # _diff.add_difference(switch_name_map[name], "Switch.open", 1, 0)
    _diff.add_difference(switch_name_map[name], "Switch.open", fv, rv)
    msg = _diff.get_message()
    return msg
예제 #3
0
def pv_msg(name, fv_p=0, fv_q=0, rv_p=0, rv_q=0):
    if name not in pv_name_map:
        print('No pv named ' + name)
        return None
    # generators = query_model.get_generators(fid_select)
    # generator_name_map = {generator['name']: generator['id'] for generator in generators}
    # msg =create_message(generator_name_map[name], "SynchronousMachine.p", 0, 0)
    # msg2 = create_message(generator_name_map[name], "SynchronousMachine.q", 0, 0)
    # msg['message']['forward_differences'].append(msg2['message']['forward_differences'][0])
    # msg['message']['forward_differences'].append(msg2['message']['forward_differences'][0])
    _diff = DifferenceBuilder(simulation_id)
    _diff.add_difference(generator_name_map[name],
                         "PowerElectronicsConnection.p", fv_p, rv_p)
    _diff.add_difference(generator_name_map[name],
                         "PowerElectronicsConnection.q", fv_q, rv_q)
    msg = _diff.get_message()
    return msg
    def on_message(self, header, message):
        # TODO workaround for broken unsubscribe method
        if not self.keepLoopingFlag:
            return

        msgdict = message['message']
        ts = msgdict['timestamp']
        print('simulation timestamp: ' + str(ts), flush=True)

        rid = self.Rids[self.rid_idx]
        reg_diff = DifferenceBuilder(self.simulation_id)
        reg_diff.add_difference(rid, 'TapChanger.step', 0, 1)
        msg = reg_diff.get_message()
        print(msg)
        self.gapps.send(self.publish_to_topic, json.dumps(msg))
        reg_diff.clear()

        self.rid_idx += 1
        if self.rid_idx == len(self.Rids):
            self.keepLoopingFlag = False
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()
예제 #6
0
class SwitchingActions(object):
    """ A simple class that handles publishing forward and reverse differences

    The object should be used as a callback from a GridAPPSD object so that the
    on_message function will get called each time a message from the simulator.  During
    the execution of on_meessage the `CapacitorToggler` object will publish a
    message to the simulation_input_topic with the forward and reverse difference specified.
    """
    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 on_message(self, headers, message):
        """ Handle incoming messages on the simulation_output_topic for the simulation_id

        Parameters
        ----------
        headers: dict
            A dictionary of headers that could be used to determine topic of origin and
            other attributes.
        message: object
            A data structure following the protocol defined in the message structure
            of ``GridAPPSD``.  Most message payloads will be serialized dictionaries, but that is
            not a requirement.
        """
        if type(message) == str:
            message = json.loads(message)

        if 'gridappsd-alarms' in headers['destination']:
            message = json.loads(message.replace("\'", ""))
            for m in message:
                print(m['created_by']), m['equipment_name']
            # print(s)

        else:
            if not message['message']['measurements']:
                return

            self._message_count += 1
            flag_fault = 0
            flag_event = 0

            Top = Topology(self.msr_mrids_loadsw, self.switches, message,
                           self.LineData)
            open_switch = Top.curr_top()
            # print(open_switch)

            d = PowerData(self.msr_mrids_demand, message, self.xfmr,
                          self.obj_msr_inv, self.LineData, open_switch,
                          self.obj_msr_node)
            platformload = d.demand()
            print('Platform Load is obtained....')

            with open('output.json', 'w') as json_file:
                json.dump(message, json_file)
            # print(messvar)

            if self._message_count % message_period == 0:

                no_opt = LEGACY_DEV(self.msr_mrids_cap, self.msr_mrids_reg,
                                    message)
                statusP_c = no_opt.cap_()
                statusP_r = no_opt.reg_()
                print('form platform capacitor switch status', statusP_c)
                print('from platform regulator tap position', statusP_r)
                # print('\n \n ........................')
                # print('Platform Status')DifferenceBuilder(simulation_id)
                # print('........................\n \n')

                ###calling VVO
                capreg_st = WSUVVO()
                statusO_c, statusO_r, flag = capreg_st.VVO9500(
                    self.LineData, platformload, open_switch, self.xfmr)
                print('\n \n ........................')
                print('Optimization results')
                print('capacitor switch status', statusO_c)
                print('regulator tap position', statusO_r)
                print('........................\n \n')

                # for inv in self.obj_msr_inv:
                #     for qpv in Qpvcontrol0:
                #         if inv['bus'] == qpv['bus']:
                #             # print(eqid)
                #             # print(mrid)
                #             qpv['mrid'] = inv['eqid']

                # print(Qpvcontrol0)

                # for qpv_mrid in Qpvcontrol0 :
                #     self._pv_qpower.add_difference(qpv_mrid['mrid'], "PowerElectronicsConnection.q", qpv_mrid['val'], 0)
                #     msg = self._pv_qpower.get_message()
                #     self._gapps.send(self._publish_to_topic, json.dumps(msg))
                #     print(msg)

                # total number of control variables are 12
                # ch = []
                # for m in range(10):
                #     if statusO_c[m] == 0:
                #         ch.append(self._cap_list[m])

                if flag == 1:
                    indx = 0
                    for cap_mrid in self._cap_list:
                        if statusO_c[indx] == None:
                            # self._close_diff.add_difference(cap_mrid, "ShuntCompensator.sections", statusP_c[indx], 1)
                            # indx += 1
                            self._cap_close_diff.add_difference(
                                cap_mrid, "ShuntCompensator.sections",
                                statusP_c[indx], 0)
                            indx += 1
                        else:
                            # self._close_diff.add_difference(cap_mrid, "ShuntCompensator.sections", statusO_c[indx], 1)
                            # indx += 1
                            self._cap_close_diff.add_difference(
                                cap_mrid, "ShuntCompensator.sections",
                                statusO_c[indx], 0)
                            indx += 1
                        msg = self._cap_close_diff.get_message()
                        self._gapps.send(self._publish_to_topic,
                                         json.dumps(msg))

                    ind = 0
                    for reg_mrid in self.reg_list:
                        # self._close_diff.add_difference(reg_mrid, "TapChanger.step", statusO_r[ind], 0)
                        self._tap_close_diff.add_difference(
                            reg_mrid, "TapChanger.step", statusO_r[ind], 0)
                        ind += 1
                        msg = self._tap_close_diff.get_message()
                        self._gapps.send(self._publish_to_topic,
                                         json.dumps(msg))
예제 #7
0
class CapacitorToggler(object):
    """ A simple class that handles publishing forward and reverse differences

    The object should be used as a callback from a GridAPPSD object so that the
    on_message function will get called each time a message from the simulator.  During
    the execution of on_meessage the `CapacitorToggler` object will publish a
    message to the simulation_input_topic with the forward and reverse difference specified.
    """
    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 on_message(self, headers, message):
        """ Handle incoming messages on the simulation_output_topic for the simulation_id

        Parameters
        ----------
        headers: dict
            A dictionary of headers that could be used to determine topic of origin and
            other attributes.
        message: object
            A data structure following the protocol defined in the message structure
            of ``GridAPPSD``.  Most message payloads will be serialized dictionaries, but that is
            not a requirement.
        """

        self._message_count += 1
        _log.debug(f"new message count is: {self._message_count}")

        # Every message_period messages we are going to turn the capcitors on or off depending
        # on the current capacitor state.
        if self._message_count % message_period == 0:
            if self._last_toggle_on:
                _log.debug("count: {} toggling off".format(
                    self._message_count))
                msg = self._close_diff.get_message(epoch=message['timestamp'])
                self._last_toggle_on = False
            else:
                _log.debug("count: {} toggling on".format(self._message_count))
                msg = self._open_diff.get_message(epoch=message['timestamp'])
                self._last_toggle_on = True

            self._gapps.send(self._publish_to_topic, json.dumps(msg))
예제 #8
0
class LearnPlatform(object):
    """ A simple class that handles publishing forward and reverse differences

    The object should be used as a callback from a GridAPPSD object so that the
    on_message function will get called each time a message from the simulator.  During
    the execution of on_meessage the `CapacitorToggler` object will publish a
    message to the simulation_input_topic with the forward and reverse difference specified.
    """
    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 on_message(self, headers, message):
        """ Handle incoming messages on the simulation_output_topic for the simulation_id

        Parameters
        ----------
        headers: dict
            A dictionary of headers that could be used to determine topic of origin and
            other attributes.
        message: object
            A data structure following the protocol defined in the message structure
            of ``GridAPPSD``.  Most message payloads will be serialized dictionaries, but that is
            not a requirement.
        """

        if type(message) == str:
            message = json.loads(message)

        # Some demo for understanding object and measurement mrids. Print the status of several switches
        timestamp = message["message"]["timestamp"]
        meas_value = message['message']['measurements']

        # Find interested mrids. We are only interested in Pos of the switches
        ds = [d for d in self._obj_msr_loadsw if d['type'] == 'Pos']

        # Store the open switches
        Loadbreak = []
        for d1 in ds:
            if d1['measid'] in meas_value:
                v = d1['measid']
                p = meas_value[v]
                if p['value'] == 0:
                    Loadbreak.append(d1['eqname'])

        print('.....................................................')
        print('The total number of open switches:', len(set(Loadbreak)))
        print(timestamp, set(Loadbreak))

        self._flag += 1
        # Open one of the switches
        if self._flag == 5:
            swmrid = '_BC63E102-37AD-4269-BB19-8351403B9B60'
            self._open_diff.add_difference(swmrid, "Switch.open", 1, 0)
            msg = self._open_diff.get_message()
            print(msg)
            self._gapps.send(self._publish_to_topic, json.dumps(msg))

            swmrid = '_7262F9C3-2E8B-4069-AA13-BF4A655ACE35'
            self._open_diff.add_difference(swmrid, "Switch.open", 0, 1)
            msg = self._open_diff.get_message()
            print(msg)
            self._gapps.send(self._publish_to_topic, json.dumps(msg))
예제 #9
0
class NodalVoltage(object):
    """ A simple class that handles publishing forward and reverse differences

    Important in handling the gridappsd platform

    The object should be used as a callback from a GridAPPSD object so that the
    on_message function will get called each time a message from the simulator.  During
    the execution of on_message the `CapacitorToggler` object will publish a
    message to the simulation_input_topic with the forward and reverse difference specified.
    """
    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``.

        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._flag = 0
        self._start_time = 0

        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 capacitor list")

    def on_message(self, headers, message):
        # this section is modified by shiva
        """ Handle incoming messages on the simulation_output_topic for the simulation_id

        Parameters
        ----------
        headers: dict
            A dictionary of headers that could be used to determine topic of origin and
            other attributes.
        message: object
            A data structure following the protocol defined in the message structure
            of ``GridAPPSD``.  Most message payloads will be serialized dictionaries, but that is
            not a requirement.
        """

        if type(message) == str:
            message = json.loads(message)

        # Some demo for understanding object and measurement mrids.
        # Print the status of several switches
        timestamp = message["message"]["timestamp"]
        meas_value = message['message']['measurements']

        # SWITCHES
        # Find interested mrids. We are only interested in Pos of the switches
        ds = [d for d in self._obj_msr_loadsw if d['type'] == 'Pos']
        print("\n ******* ds ********* \n ")
        print(ds)

        # Store the open switches
        Loadbreak = []
        for d1 in ds:
            if d1['measid'] in meas_value:
                v = d1['measid']
                p = meas_value[v]
                if p['value'] == 0:
                    Loadbreak.append(d1['eqname'])

        print('.....................................................')
        print('The total number of open switches:', len(set(Loadbreak)))
        print(timestamp, set(Loadbreak))
        # print(sh)

        # PNV
        # Find interested mrids. We are only interested in PNV
        phase_check = [d for d in self._ACline if d['phases'] == 'A']
        print("\n ******* phase check ********* \n ")
        print(phase_check)
        # print(sh)

        # Store the open switches
        phaseA_PNV = []
        for d1 in phase_check:
            if d1['measid'] in meas_value:
                v = d1['measid']
                p = meas_value[v]
                # print ('\n p \n', p)
                # print(sh)
                if p['magnitude'] > 2000 and p['magnitude'] < 4000:
                    phaseA_PNV.append(d1['bus'])

        print('.....................................................')
        print('The total number of nodes with PNV > 2000 and PNV < 4000 = ',
              len(set(phaseA_PNV)))
        print("timestamp: {} and the set of buses are: {}".format(
            timestamp, set(phaseA_PNV)))
        print(sh)

        # Open one of the switches
        if self._flag == 0:
            swmrid = '_BC63E102-37AD-4269-BB19-8351403B9B60'
            self._open_diff.add_difference(
                swmrid, "Switch.open", 1,
                0)  # (1,0) -> (current_state, next_state)
            msg = self._open_diff.get_message()
            print(msg)
            # send the message to platform
            self._gapps.send(self._publish_to_topic, json.dumps(msg))

            swmrid = '_7262F9C3-2E8B-4069-AA13-BF4A655ACE35'
            self._open_diff.add_difference(swmrid, "Switch.open", 0, 1)
            msg = self._open_diff.get_message()
            print(msg)
            self._gapps.send(self._publish_to_topic, json.dumps(msg))
            self._flag = 1
예제 #10
0
class NodalVoltage(object):
    """ A simple class that handles publishing forward and reverse differences

	Important in handling the gridappsd platform

	The object should be used as a callback from a GridAPPSD object so that the
	on_message function will get called each time a message from the simulator.  During
	the execution of on_message the `CapacitorToggler` object will publish a
	message to the simulation_input_topic with the forward and reverse difference specified.
	"""
    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 on_message(self, headers, message):
        # this section is modified by shiva
        """ Handle incoming messages on the simulation_output_topic for the simulation_id

		Parameters
		----------
		headers: dict
		    A dictionary of headers that could be used to determine topic of origin and
		    other attributes.
		message: object
		    A data structure following the protocol defined in the message structure
		    of ``GridAPPSD``.  Most message payloads will be serialized dictionaries, but that is
		    not a requirement.
		"""

        if type(message) == str:
            message = json.loads(message)

        # Some demo for understanding object and measurement mrids.
        # Print the status of several switches
        timestamp = message["message"]["timestamp"]
        meas_value = message['message']['measurements']

        print(self._obj_msr_reg)
        print(sh)

        # *************************** Regulator ********************************

        # get the operating position of regulator
        reg_position = [d for d in self._obj_msr_reg if d['type'] == 'Pos']
        #print ("\n ******* reg_position ********* \n ")
        #print(reg_position)
        #print(sh)

        # Store the regulator positions
        regulators_tap = []
        for iter_reg_pos in reg_position:
            if iter_reg_pos['measid'] in meas_value:
                v = iter_reg_pos['measid']
                p = meas_value[v]
                regulators_tap.append(p)

        print('\n.................   regulator tap   ...............\n')
        #print('The total regulators', len(set(regulators_tap)))
        #print(timestamp, set(regulators_tap))
        #print(regulators_tap)
        # print (sh)

        # changing the tap position of the regulator
        reg_mrid = [x for x in regulators_tap if x['value'] == 0]
        print(reg_mrid)
        #print(sh)

        print("################ self regulators #####################")
        print(self._regulators)

        measid = [d for d in self._regulators if d['name'] == 'creg2a']
        print("############# measid ###############")
        print(measid[0]['mrid'])
        print('############# measidtype ###############')
        print(type(measid[0]))

        self._tap_close_diff.add_difference(measid[0]['mrid'],
                                            "TapChanger.step", 5, 0)
        # send the message to platform
        msg = self._tap_close_diff.get_message()
        print(msg)
        self._gapps.send(self._publish_to_topic, json.dumps(msg))
        #print(sh)

        # *************************** SWITCHES ********************************
        # Find interested mrids. We are only interested in Pos of the switches
        switch_position = [
            d for d in self._obj_msr_loadsw if d['type'] == 'Pos'
        ]
        #print ("\n ******* switch_position ********* \n ")
        #print(switch_position)

        # Store the open switches
        Loadbreak = []
        for iter_sw_pos in switch_position:
            if iter_sw_pos['measid'] in meas_value:
                v = iter_sw_pos['measid']
                p = meas_value[v]
                if p['value'] == 0:
                    Loadbreak.append(iter_sw_pos['eqname'])

        print('.....................................................')
        print('The total number of open switches:', len(set(Loadbreak)))
        print(timestamp, set(Loadbreak))

        print(
            "For now we can only allow you to view Phase-to-Neutral Voltage related information"
        )
        phase_checking = ['A', 'B', 'C']
        while (self.check):

            while not (self.inp):
                phase_val = input(
                    "Which phase are you interested in (A/B/C)? ")
                self.inp = True if phase_val in phase_checking else print(
                    'Unidentified phase')
            print("Selecting Phase as ** {} ** -- ...".format(phase_val))
            time.sleep(3)

            # PNV
            # Find interested mrids. We are only interested in PNV of specific phase
            phase_check = [d for d in self._ACline if d['phases'] == phase_val]
            # print ("\n ******* phase check ********* \n ")
            # print (phase_check)
            # print(sh)

            # get the ranges
            min_volt = float(
                input("Minimum value of voltage at phase {}? ".format(
                    phase_val)))
            max_volt = float(
                input("Maximum value of voltage at phase {}? ".format(
                    phase_val)))

            phase_PNV = []
            for d1 in phase_check:
                if d1['measid'] in meas_value:
                    v = d1['measid']
                    p = meas_value[v]
                    # print ('\n p \n', p)
                    # print(sh)
                    if p['magnitude'] > min_volt and p['magnitude'] < max_volt:
                        phase_PNV.append(d1['bus'])

            print('.....................................................')
            print('The total number of nodes with PNV > {} and PNV < {} = {} '.
                  format(min_volt, max_volt, len(set(phase_PNV))))
            print("timestamp: {} and the set of buses are: {}".format(
                timestamp, set(phase_PNV)))
            recheck = input("Do you want another option (Y/N)? ")
            if recheck == 'N':
                self.check = False

            self.inp = False

        # print(sh)
        self.check = True
        print('---------------------------------------')
        print("Now let's try working on the switches")
        print('---------------------------------------')

        switch_val = input(
            "Are you interesting in toggling the switches (Y/N)? ")
        # print("\n ************** check ********************* \n")
        # print(self._switches[0]['mrid'])
        #print(sh)

        if (switch_val == 'Y'):
            sel_sw = int(input("select the switch to toggle (0-7)"))

            # Open one of the switches
            if self._flag == 0:
                # swmrid = '_BC63E102-37AD-4269-BB19-8351403B9B60'
                # self._open_diff.add_difference(swmrid, "Switch.open", 1, 0) # (1,0) -> (current_state, next_state)
                # msg = self._open_diff.get_message()
                # print(msg)
                # send the message to platform
                # self._gapps.send(self._publish_to_topic, json.dumps(msg))

                #swmrid = '_7262F9C3-2E8B-4069-AA13-BF4A655ACE35'
                #self._open_diff.add_difference(swmrid, "Switch.open", 0, 1)
                #msg = self._open_diff.get_message()
                #print(msg)
                #self._gapps.send(self._publish_to_topic, json.dumps(msg))
                #self._flag = 1

                swmrid = self._switches[sel_sw]['mrid']
                self._open_diff.add_difference(swmrid, "Switch.open", 1, 0)
                # (1,0) -> (current_state, next_state)
                msg = self._open_diff.get_message()
                print(msg)
                # send the message to platform
                self._gapps.send(self._publish_to_topic, json.dumps(msg))
예제 #11
0
class SwitchingActions(object):
    """ A simple class that handles publishing forward and reverse differences

    The object should be used as a callback from a GridAPPSD object so that the
    on_message function will get called each time a message from the simulator.  During
    the execution of on_meessage the `CapacitorToggler` object will publish a
    message to the simulation_input_topic with the forward and reverse difference specified.
    """

    def __init__(self, simulation_id, gridappsd_obj, switches, msr_mrids_loadsw, msr_mrids_demand, demand, line):
        """ 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._store = []
        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.msr_mrids_loadsw = msr_mrids_loadsw
        self.msr_mrids_demand = msr_mrids_demand
        self.LineData = line
        self.DemandData  = demand
        self.switches  = switches
        self.TOP = []
        self.flag_res = 0
        _log.info("Building cappacitor list")

        
    def on_message(self, headers, message):
        """ Handle incoming messages on the simulation_output_topic for the simulation_id

        Parameters
        ----------
        headers: dict
            A dictionary of headers that could be used to determine topic of origin and
            other attributes.
        message: object
            A data structure following the protocol defined in the message structure
            of ``GridAPPSD``.  Most message payloads will be serialized dictionaries, but that is
            not a requirement.
        """

        self._message_count += 1
        flag_fault = 0
        flag_event = 0

        # Checking the topology everytime communicating with the platform
        if self.flag_res == 0:
            top = Topology(self.msr_mrids_loadsw, self.switches, message, self.TOP, self.LineData)
            TOP, flag_event = top.curr_top()
            self.TOP = TOP

        #Locate fault
        if flag_event == 1:
            flag_fault, fault = top.locate_fault()

        # Get consumer loads from platform
        # Not always working so commenting it for now
        # if self.flag_load == 0:
        # ld = PowerData(self.msr_mrids_demand, message)
        # ld.demand()
        # self.flag_load = 1

        # Isolate and restore the fault
        if flag_fault == 1 and self.flag_res == 0:
            print('Forming the optimization problem.........')
            res = Restoration()
            op, cl, = res.res9500(self.LineData, self.DemandData, fault)
            # print (op, cl)
            sw_oc = SW_MRID(op, cl, self.switches, self.LineData)
            op_mrid, cl_mrid = sw_oc.mapping()
            # print (op_mrid)
            # print(cl_mrid)   
            
            # Now reconfiguring the test case in Platform based on obtained MRIDs to mimic black sky event
            for sw_mrid in op_mrid:
                self._open_diff.add_difference(sw_mrid, "Switch.open", 1, 0)
                msg = self._open_diff.get_message()
                self._gapps.send(self._publish_to_topic, json.dumps(msg))  

            for sw_mrid in cl_mrid:
                self._open_diff.add_difference(sw_mrid, "Switch.open", 0, 1)
                msg = self._open_diff.get_message()
                self._gapps.send(self._publish_to_topic, json.dumps(msg))  
            self.flag_res = 1 
            print('Event #1 Successfully restored......')