def __init__(self, data, ALG = 'CW', voltage_tolerance = 1e-15, api_path = None): self.lines = tuple((line['from'], line['to'], line['R'], line['X'], line['B'], ) for line in data['lines']) self.no_lines = len(self.lines) self.no_buses = max(self.lines, key = itemgetter(1))[1] + 1 # +1 because the bus indices start from 0 self.baseV = data['base_quantities']['V'] self.baseS = data['base_quantities']['S'] self.Ybase = self.baseS / (self.baseV * self.baseV) self.tolerance = voltage_tolerance #Compute the admittance matrix. self.__admittance_matrix() self.siY = self.__puY * self.Ybase self.algorithm = ALG if self.algorithm == 'CW': self.__puYll = delete(delete(self.__puY, 0, 0), 0, 1) self.__puP, self.__puL, self.__puU = lu(self.__puYll) self.__puYllInv = inv(self.__puYll) if api_path is not None: from snippets import load_api, dump_api api = load_api(api_path, check_readiness = False) api.base_quantities = data['base_quantities'] dump_api(api, api_path)
def main(): # Parse the arguments. parser = ArgumentParser( description="Grid sensor module that communicates with the grid agent." ) parser.add_argument("config_path", help="Path to the JSON config file for the sensor", nargs='?', default='sensor_config.json') parser.add_argument("log_path", help="Path to the log directory for the grid", nargs='?') parser.add_argument( "host_ip_mapping_path", help="Path to the JSON config file for the host ip mapping", nargs='?') parser.add_argument("--api_path", help="Path to which the GridAPI will be pickled", default='grid_api.pickle') args = parser.parse_args() # Load the configuration file. config = load_json_file(args.config_path, logger) host_ip_mapping = load_json_file(args.host_ip_mapping_path, logger) # Read the initialization values. sending_freq = config['sensed_info_sending_freq'] / 1e3 # In seconds. line_frequency = config['line_frequency']['line_frequency'] use_trace = config['line_frequency']['use_trace'] trace_file_path = config['line_frequency']['trace_file_path'] bus_indices = config['sensed_bus_indices'] addrs = [] for receiver in config['receivers_of_sensed_info']: addrs.append((host_ip_mapping[receiver['host_name']].split('/')[0], receiver['listen_port'])) # Load the GridAPI, and make sure it's ready. api = load_api(args.api_path) state_queue = Queue() # Start a thread that will continuously update the data from the grid. Thread(target=update, args=(api, bus_indices, line_frequency, sending_freq, use_trace, trace_file_path, state_queue)).start() log_path = args.log_path Process(target=log_generator, args=(state_queue, log_path)).start() # Send messages periodically using a non-blocking socket. sock = socket(AF_INET, SOCK_DGRAM) sock.setblocking(False) while True: start_time = default_timer() send(sock, addrs) elapsed_time = default_timer() - start_time sleep(sending_freq - elapsed_time % sending_freq)
def main(): # Parse the arguments. parser = ArgumentParser( description="Load that communicates with its resource agent.") parser.add_argument('config_path', help="Path to the JSON config file for the Load") parser.add_argument('--api_path', help="Path to which the GridAPI will be pickled", default='grid_api.pickle') parser.add_argument('--params_path', help="Path to file containing the Load parameters") args = parser.parse_args() # Load the configuration files. params = {} config = load_json_file(args.config_path, logger) if args.params_path == None: params = config else: params = load_json_file(args.params_path, logger) # Load the GridAPI. api = load_api(args.api_path) # Extract some relevant things out of the configuration. bus_index = config['bus_index'] load_path = config['trace_file_abs_path'] Load_addr = api.grid_ip, config['port'] RA_addr = config['RA']['ip'], config['RA']['port'] # Read in the Load parameters. sample_period = params['sample_period'] / 1e3 update_period = params['update_period'] / 1e3 queue = Queue() state = {'P': 0, 'Q': 0} queue.put(state) # Communicate with the RA. Thread(target=send, args=(RA_addr, state, update_period)).start() # Run the log generation. log_path = config['log_path'] Process(target=generate_log, args=(queue, log_path)).start() try: with open(load_path, 'r') as load_file: load = load_file.read().splitlines() load = [float(S) for S in load] except OSError as e: logger.error("Could not open {}: {}".format(load_path, e)) return 1 reference_time = default_timer() while True: start_time = default_timer() num_samples = (default_timer() - reference_time) // sample_period num_samples = int(num_samples) % len(load) S = load[num_samples] * 1e3 state['P'] = S * POWER_FACTOR state['Q'] = S * sqrt(1 - (POWER_FACTOR * POWER_FACTOR)) logger.info( "Implementing setpoint at index {}, (Pd = {}, Qd = {})".format( bus_index, state['P'], state['Q'])) api.implement_setpoint(bus_index, state['P'], state['Q']) queue.put(state) elapsed_time = default_timer() - start_time if elapsed_time < sample_period: sleep(sample_period - elapsed_time % sample_period)
def main(): # Parse the arguments. parser = ArgumentParser( description="Battery that communicates with its resource agent.") parser.add_argument("config_path", help="Path to the JSON config file for the battery") parser.add_argument("--api_path", help="Path to which the GridAPI will be pickled", default='grid_api.pickle') args = parser.parse_args() # Load the configuration file. config = load_json_file(args.config_path, logger) # Load the GridAPI. api = load_api(args.api_path) # Extract configuration information. bus_index = config['bus_index'] listen_addr = '127.0.0.1', config['listen_port'] reply_addr = config['RA']['ip'], config['RA']['listen_port'] log_path = config['log_path'] # refresh period of the battery. state_refresh_period = config[ 'refresh_period_for_battery_state'] / 1e3 # Convert to seconds. # Read in the battery parameters. Battery.LUT = config['cell']['LUT'] Battery.measurementSoCpoints = Battery.LUT['SoC'] Battery.inverter_efficiency = config['inverter_efficiency'] Battery.inverterPowerSlewRate = config['inverterPowerSlewRate'] initialSoC = config['initialSoC'] initialP = config['initialP'] initialQ = config['initialQ'] inverter_Vmin = config['inverter_Vmin'] inverter_Vmax = config['inverter_Vmax'] ratedE = config['ratedE'] ratedE_cell = config['cell']['ratedE'] # if initialP < 0, the battery is charging initialPdc = initialP * Battery.inverter_efficiency if initialP <= 0 else initialP / Battery.inverter_efficiency state = { param: interp(initialSoC, Battery.measurementSoCpoints, values) for param, values in Battery.LUT.items() } min_Em = min(Battery.LUT['Em']) max_Em = max(Battery.LUT['Em']) N = ceil(ratedE / ratedE_cell) # total number of cells possibleNs = [ i for i in range(1, N + 1) if min_Em * i >= inverter_Vmin and max_Em * i <= inverter_Vmax ] # possible number of cells in series possibleNp = [round(N / Ns) for Ns in possibleNs] # possible number of cells in parallel diffs = [(Ns, Np, fabs(N - (Ns * Np))) for Ns, Np in zip(possibleNs, possibleNp)] Ns, Np, _ = min(diffs, key=lambda t: t[2]) # Initial DC voltage is equal to the measured DC voltage at each cell multiplied by the number of cells in series initialU = state['Em'] * Ns # initialU = Em(SoC_initial) * Ns # Idc should be computed from initialU (U at initial SoC) initialIdc = initialPdc / initialU # maxCurrentHourCapacityPerColumnOfCells = ratedEbattery / ( Em(1) * Ns) state = { param: interp(1, Battery.measurementSoCpoints, values) for param, values in Battery.LUT.items() } maxCurrentHourCapacityPerColumnOfCells = ratedE * 1000 / ( state['Em'] * Ns ) # As ratedE is in kWh, to get the Ampere-Hour (not kilo Ampere-Hour) max capacity, we multiply by 1000 # Initialize the battery. battery = Battery(initialU, initialSoC, initialP, initialQ, initialIdc, maxCurrentHourCapacityPerColumnOfCells, Ns, Np, listen_addr, reply_addr) # Run the log generator. state_queue = Queue() state_queue.put(battery.state) Process(target=log_generator, args=(state_queue, log_path)).start() # Run the RA listener... Thread(target=battery.update).start() lastImplementedP = lastImplementedQ = 0 waiting_time = state_refresh_period while True: start_time = default_timer() logger.info("Implementing (P = {}, Q = {})".format( battery.P, battery.Q)) if battery.P != lastImplementedP or battery.Q != lastImplementedQ: api.implement_setpoint(bus_index, battery.P, battery.Q) lastImplementedP = battery.P lastImplementedQ = battery.Q battery.implement(waiting_time) state_queue.put(battery.state) battery.send() elapsed_time = default_timer() - start_time if elapsed_time < state_refresh_period: remaining_time = state_refresh_period - elapsed_time sleep(remaining_time) waiting_time = state_refresh_period else: waiting_time = elapsed_time
def main(): # Parse the arguments. parser = ArgumentParser( description="UCPV that communicates with its resource agent.") parser.add_argument('config_path', help="Path to the JSON config file for the UCPV") parser.add_argument('--api_path', help="Path to which the GridAPI will be pickled", default='grid_api.pickle') parser.add_argument('--params_path', help="Path to file containing the UCPV parameters") args = parser.parse_args() # Load the configuration files. params = {} config = load_json_file(args.config_path, logger) if args.params_path is None: params = config else: params = load_json_file(args.params_path, logger) # Extract some relevant things out of the configuration. bus_index = config['bus_index'] irradiance_path = config['irradiance_trace_file_path'] ucpv_ra_addr = config['RA']['ip'], config['RA']['listen_port'] log_path = config['log_path'] # Read in the UCPV parameters. update_period = params[ 'update_period'] / 1e3 # convert to seconds from milli seconds rated_power_dc_side = params['rated_power_dc_side'] converter_efficiency = params['converter_efficiency'] S_STC = params['S_STC'] # Standard test condition try: with open(irradiance_path, 'r') as f: reader_ = reader(f, quoting=QUOTE_NONNUMERIC) irradiance = list(reader_) except IOError as e: logger.error("Could not open {}: {}".format(irradiance_path, e)) return 1 except ValueError as e: logger.error("ValueError, wrong or missing value in {}: {}".format( irradiance_path, e)) return 1 # normalize the trace timestamp first_irradiance_ts = irradiance[0][0] for i in range(0, len(irradiance)): irradiance[i][0] = irradiance[i][0] - first_irradiance_ts state_queue = Queue() state = {'P': 0, 'Q': 0, 'Ts': 0} # Load the GridAPI. api = load_api(args.api_path) # Communicate with the RA. Thread(target=send, args=(ucpv_ra_addr, state, update_period)).start() # Run the log generation. Process(target=generate_log, args=(state_queue, log_path)).start() state['Ts'] = datetime.now() state_queue.put(state) ptr_ID = 0 P = irradiance[ptr_ID][ 1] * rated_power_dc_side / S_STC * converter_efficiency reference_time = default_timer() sleep_time = 0 while True: state['P'] = P logger.info( "Implementing setpoint at index {}, (Pd = {}, Qd = {})".format( ptr_ID, state['P'], state['Q'])) api.implement_setpoint(bus_index, state['P'], state['Q']) state['Ts'] = datetime.now() state_queue.put(state) if (ptr_ID + 1) >= len(irradiance): ptr_ID = 0 P = irradiance[ptr_ID][ 1] * rated_power_dc_side / S_STC * converter_efficiency sleep(sleep_time) reference_time = default_timer() continue else: ptr_ID = ptr_ID + 1 next_sample_time = irradiance[ptr_ID][0] P = irradiance[ptr_ID][ 1] * rated_power_dc_side / S_STC * converter_efficiency sleep_time = next_sample_time - (default_timer() - reference_time) if sleep_time > 0: sleep(sleep_time)
def main(): # Parse the arguments. parser = argparse.ArgumentParser( description= "EV Charging Station that communicates with its resource agent.") parser.add_argument('config_path', help="Path to the JSON config file for the CS") parser.add_argument('--api_path', help="Path to which the GridAPI will be pickled", default='grid_api.pickle') parser.add_argument('--params_path', help="Path to file containing the CS parameters", default='evcs_config.json') args = parser.parse_args() # Load the configuration files. config = load_json_file(args.config_path, logger) # TODO: Load the params from the config file... #params = load_json_file(args.params_path, logger) # Load the GridAPI. api = load_api(args.api_path) # Extract some relevant things out of the configuration. bus_index = config['bus_index'] listen_addr = api.grid_ip, config['port'] #listen_addr = '127.0.0.1', config['port'] reply_addr = config['RA']['ip'], config['RA']['port'] #reply_addr = '127.0.0.1', config['RA']['port'] arriv_depart_addr = config['RA'][ 'ip'], UDP_PORT_CSA_LISTENS_CSM_ARRIVAL_DEPARTURE_EVENTS #arriv_depart_addr = '127.0.0.1', UDP_PORT_CSA_LISTENS_CSM_ARRIVAL_DEPARTURE_EVENTS print("DEBUG: Starting a new thread to listen for COMMANDS from CSA...". format()) # Run the listener service. Thread(target=listen_from_csa, args=(listen_addr, )).start() print( "DEBUG: Starting a new thread to periodically update implemented setpoint for each EV and send them to CSA..." .format()) # Run the thread to periodically update implemented setpoint for each EV and send them to CSA... Thread(target=update_and_send_measurements, args=( bus_index, api, reply_addr, arriv_depart_addr, )).start() if SIMULATION_FROM_ONE_DAY_ARRIVAL_TRACE == True: print('DEBUG: Arrivals from one day trace...') # Read arrivals from trace (instead of generating new arrivals each time) arrivals = [] with open('arrivals_in_secs_with_400_max_charging_slots.csv', 'r') as f: reader = csv.reader(f) arrivals = list(reader) last_arrival = 0 #arrivals = [15, 50, 100, 150, 200, 250, 500] # for testing for arrival in arrivals: arrival = float(arrival[1]) time_to_next_arrival = arrival - last_arrival last_arrival = arrival print('DEBUG: Time to next arrival is {} secs.'.format( time_to_next_arrival)) print('DEBUG: Going to sleep up to the next arrival...') sleep(time_to_next_arrival) print("DEBUG: New EV arrived! Current time is {} secs.".format( arrival)) lock.acquire() slot_no, stay_time = execute_arrival_and_send_msg_csa( arrival, arriv_depart_addr) lock.release() # schedule the departure event Timer(stay_time, simulate_departure, ( slot_no, arriv_depart_addr, )).start() else: print( 'DEBUG: Arrivals from a new infinite non-homogeneous poisson process...' ) # the average rate of arrival of cars per minute # in a non-homogeneous Poisson process # in a given interval, the rate of arrival is assumed to be # constant and independent of each other def rate(t): t = t % 1440 if t >= 0 and t < 480: hourly_rate = 20 elif t >= 480 and t < 720: hourly_rate = 90 elif t >= 720 and t < 1080: hourly_rate = 30 elif t >= 1080 and t < 1200: hourly_rate = 150 else: hourly_rate = 15 return hourly_rate / 60 max_rate = 150 / 60 print( "DEBUG: Maximum rate of arrival per minute during the day is {}.". format(max_rate)) current_time = SIM_START_TIME print( "DEBUG: Starting the simulation at time {} (number of minutes after the midnight)." .format(current_time)) print("DEBUG: Occupied slots are initially {}.".format( len(occupied_slots))) accumulated_arrival_time = 0 while True: arrival_time = -math.log(1.0 - random.random()) / max_rate current_time += arrival_time accumulated_arrival_time += arrival_time if (random.random() <= rate(current_time) / max_rate and len(occupied_slots) < NO_CHARGING_SLOTS): print('DEBUG: Time to next arrival is {} secs.'.format( accumulated_arrival_time * 60)) print('DEBUG: Going to sleep up to the next arrival...') sleep(accumulated_arrival_time * 60) print("DEBUG: New EV arrived! Current time is {} mins.".format( current_time)) lock.acquire() slot_no, stay_time = execute_arrival_and_send_msg_csa( current_time, arriv_depart_addr) lock.release() # schedule the departure event Timer(stay_time, simulate_departure, ( slot_no, arriv_depart_addr, )).start() accumulated_arrival_time = 0