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
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"))
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))
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))
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))
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))
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}")
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}")