Esempio n. 1
0
    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)
Esempio n. 2
0
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)
Esempio n. 3
0
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)
Esempio n. 4
0
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
Esempio n. 5
0
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)
Esempio n. 6
0
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