예제 #1
0
    def __init__(self, cfg):
        super().__init__(cfg)
        # TODO: store Vmag of previous timestep for HIL implementation (only 1 timestep at a time...)

        # Create whatever instance variables + initialization you want here.
        # Pass options in using the 'cfg' dictionary
        
        # define system phase size to define size of phasor reference
        #phase_size, feeder_init = feeder_init() ## doesnt work inside of __init__

        
        # This particular implementation calls the self.compute_and_announce function
        # every 3 seconds; the self.compute_and_announce contains the optimization function
        # that produces the phasor target for each LPBC
        schedule(self.call_periodic(30, self.compute_and_announce))
        ### set some refphasor variable == true/false to determine length of schedule
        
         #~~ initialize values ~~#
        self.iteration = -1
        # self.P_flag = []
        # self.Q_flag = []
        if TV_load == True:
            self.timestepcur = start_hour*60-1
        else:
            self.timestepcur = start_hour*60
        
        ''' # add initializtion of LPBC nodes here, and then add update in loop
예제 #2
0
    def __init__(self, cfg):
        super().__init__(cfg)
        if 'namespace' not in cfg:
            raise ConfigMissingError('namespace')
        if 'name' not in cfg:
            raise ConfigMissingError('name')
        if 'reference_channels' not in cfg:
            raise ConfigMissingError('reference_channels')
        self.namespace = b64decode(cfg['namespace'])
        self._log.info(f"initialized SPBC: {cfg}")
        self.name = cfg['name']

        # reference channels are URIs for the uPMU channels the SPBC
        # subscribes to. The SPBC framework maintains self.reference_phasors
        # to contain the most recent phasor measurements for each channel
        self._reference_channels = cfg['reference_channels']
        self.reference_phasors = {k: None for k in self._reference_channels}
        for channel in self._reference_channels:
            upmu_uri = f"upmu/{channel}"
            self._log.info(f"Subscribing to {channel} as reference phasor")
            schedule(
                self.subscribe_extract(self.namespace, upmu_uri,
                                       ".C37DataFrame", self._upmucb,
                                       "spbc_reference"))

        self.lpbcs = {}
        schedule(
            self.subscribe_extract(self.namespace, "lpbc/*",
                                   ".EnergiseMessage.LPBCStatus", self._lpbccb,
                                   "lpbc_status"))
예제 #3
0
    def __init__(self, cfg):
        super().__init__(cfg)
        self.p = 10
        self.q = 20

        # recalculate every 30 seconds
        schedule(self.call_periodic(30, self.compute_and_announce))
예제 #4
0
    def __init__(self, cfg):
        super().__init__(cfg)

        # Create whatever instance variables + initialization you want here.
        # Pass options in using the 'cfg' dictionary

        # This particular implementation calls the self.compute_and_announce function
        # every 3 seconds; the self.compute_and_announce contains the optimization function
        # that produces the phasor target for each LPBC
        schedule(self.call_periodic(3, self.compute_and_announce))
예제 #5
0
    def __init__(self, cfg):
        super().__init__(cfg)
        if 'namespace' not in cfg:
            raise ConfigMissingError('namespace')
        elif 'name' not in cfg:
            raise ConfigMissingError('name')
        self.namespace = b64decode(cfg['namespace'])
        self._log.info(f"initialized SPBC: {cfg}")
        self.name = cfg['name']

        self.lpbcs = {}
        schedule(
            self.subscribe_extract(self.namespace, "lpbc/*",
                                   ".EnergiseMessage.LPBCStatus",
                                   self._lpbccb))
예제 #6
0
    def log_actuation(self, actuation):
        """
        Publish an EnergiseMessage.ActuatorCommand message containing the parameters that were
        sent to and received from the inverters, etc.
        The 'actuation' argument has the following structure, and is expected to be a dictionary:

            {
                "phases": ["a","b","c"],
                "P_cmd": [10.1, 20.2, 30.3],
                "Q_cmd": [10.9, 20.9, 30.9],
                "P_act": [.1, .2, .3],
                "Q_act": [.1, .2, .3],
                "P_PV": [11.1,22.2,33.3],
                "Batt_cmd": [99.1, 99.2, 99.3],
                "pf_ctrl": [8.7,6.5,5.4]
            }

        All of the values are lists of floats and should have the same length as the 'phases' key.
        """
        components = [
            'phases', 'P_cmd', 'Q_cmd', 'P_act', 'Q_act', 'P_PV', 'Batt_cmd',
            'pf_ctrl'
        ]
        for required in components:
            if required not in actuation:
                raise Exception(f"Need {required} key in dictionary")
        num_components = len(actuation['phases'])
        for component in components:
            if len(actuation[component]) != num_components:
                raise Exception(
                    f"Field {component} needs to be of length {num_components} to match number of phases"
                )

        msg = XBOS(EnergiseMessage=EnergiseMessage(
            ActuatorCommand=ActuatorCommand(
                time=int(datetime.utcnow().timestamp() * 1e9),
                nodeID=self.name,
                phases=actuation["phases"],
                P_cmd=actuation["P_cmd"],
                Q_cmd=actuation["Q_cmd"],
                P_act=actuation["P_act"],
                Q_act=actuation["Q_act"],
                P_PV=actuation["P_PV"],
                Batt_cmd=actuation["Batt_cmd"],
                pf_ctrl=actuation["pf_ctrl"],
            )))
        schedule(
            self.publish(self.namespace, f"lpbc/{self.name}/actuation", msg))
예제 #7
0
    def __init__(self, cfg):
        super().__init__(cfg)
        if 'namespace' not in cfg:
            raise ConfigMissingError('namespace')
        self.namespace = b64decode(cfg['namespace'])
        if 'upmu' not in cfg:
            raise ConfigMissingError('upmu')
        if 'name' not in cfg:
            raise ConfigMissingError('name')
        if 'spbc' not in cfg:
            raise ConfigMissingError('spbc')
        if 'rate' not in cfg:
            raise ConfigMissingError('rate')
        self.upmu = cfg['upmu']
        self.name = cfg['name']
        self.spbc = cfg['spbc']
        self._rate = int(cfg['rate'])
        self.last_upmu_reading = None
        self.last_spbc_command = None
        self.control_on = False

        schedule(
            self.subscribe_extract(self.namespace, f"upmu/{self.upmu}",
                                   ".C37DataFrame", self._upmucb))
        schedule(
            self.subscribe_extract(self.namespace, f"spbc/{self.spbc}",
                                   ".EnergiseMessage.SPBC", self._spbccb))

        schedule(self.call_periodic(self._rate, self._trigger, runfirst=False))

        self._log.info(f"initialized LPBC: {cfg}")
예제 #8
0
    def __init__(self, cfg):
        super().__init__(cfg)
        if 'namespace' not in cfg:
            raise ConfigMissingError('namespace')
        self.namespace = b64decode(cfg['namespace'])
        if 'local_channels' not in cfg:
            raise ConfigMissingError('local_channels')
        if 'reference_channels' not in cfg:
            raise ConfigMissingError('reference_channels')
        if 'name' not in cfg:
            raise ConfigMissingError('name')
        if 'spbc' not in cfg:
            raise ConfigMissingError('spbc')
        if 'rate' not in cfg:
            raise ConfigMissingError('rate')

        # locks
        self._reference_phasor_lock = asyncio.Lock()
        self._local_phasor_lock = asyncio.Lock()

        self.local_channels = cfg['local_channels']
        self.reference_channels = cfg['reference_channels']

        self.name = cfg['name']
        self.spbc = cfg['spbc']
        self._rate = int(cfg['rate'])

        # local buffers for phasor data
        # key: channel name, value: phasor data
        self.local_phasor_data = {}
        self.reference_phasor_data = {}
        self.last_spbc_command = None
        self.control_on = False

        for local_channel in self.local_channels:
            self.local_phasor_data[local_channel] = []
            cb = partial(self._local_upmucb, local_channel)
            schedule(
                self.subscribe_extract(self.namespace, f"upmu/{local_channel}",
                                       ".C37DataFrame", cb,
                                       f"local_channel_{local_channel}"))
        for reference_channel in self.reference_channels:
            self.reference_phasor_data[reference_channel] = []
            cb = partial(self._reference_upmucb, reference_channel)
            schedule(
                self.subscribe_extract(
                    self.namespace, f"upmu/{reference_channel}",
                    ".C37DataFrame", cb,
                    f"reference_phasor_{reference_channel}"))

        # TODO: listen to SPBC
        print(f"spbc/{self.spbc}/node/{self.name}")
        schedule(
            self.subscribe_extract(self.namespace,
                                   f"spbc/{self.spbc}/node/{self.name}",
                                   ".EnergiseMessage.SPBC", self._spbccb,
                                   "spbc_sub"))

        schedule(self.call_periodic(self._rate, self._trigger, runfirst=False))

        self._log.info(f"initialized LPBC: {cfg}")