logger.debug(f'\tCharging current (A): {charging_current:.2f}') added_energy = (charging_current * charging_voltage * \ update_interval/3600) / 1000 logger.debug(f'\tAdded energy (kWh): {added_energy:.4f}') current_soc[j] = current_soc[j] + added_energy / batt_list[j] logger.debug(f'\tSOC: {current_soc[j]:.4f}') else: logger.debug(f'\tNo messages at endpoint {endpoint_name} ' f'recieved at ' f'time {grantedtime}') # send charging current message # to this endpoint's default destination, "" h.helicsEndpointSendBytesTo(endid[j], str(charging_current), "") # logger.debug(f'Sent message {charging_current:.2f}' f'from endpoint {endpoint_name}' f' at time {grantedtime}') # Store SOC for later analysis/graphing if endid[j] not in soc: soc[endid[j]] = [] soc[endid[j]].append(float(current_soc[j])) # Data collection vectors time_sim.append(grantedtime) # Cleaning up HELICS stuff once we've finished the co-simulation. destroy_federate(fed) # Printing out final results graphs for comparison/diagnostic purposes.
# Data collection lists time_sim = [] power = [] charging_current = {} # Blocking call for a time request at simulation time 0 initial_time = 60 logger.debug(f'Requesting initial time {initial_time}') grantedtime = h.helicsFederateRequestTime(fed, initial_time) logger.debug(f'Granted time {grantedtime}') # Apply initial charging voltage for j in range(0, end_count): message = str(charging_voltage[j]) h.helicsEndpointSendBytesTo(endid[j], "", message.encode()) # logger.debug(f'\tSending charging voltage of {message} ' f' from {endid[j]}' f' at time {grantedtime}') ########## Main co-simulation loop ######################################## # As long as granted time is in the time range to be simulated... while grantedtime < total_interval: # Time request for the next physical interval to be simulated requested_time = (grantedtime + update_interval) logger.debug(f'Requesting time {requested_time}') grantedtime = h.helicsFederateRequestTime(fed, requested_time) logger.debug(f'Granted time {grantedtime}') for j in range(0, end_count):
else: logger.debug(f'\tNo messages at endpoint {endpoint_name} ' f'recieved at ' f'time {grantedtime}') # Publish updated charging voltage h.helicsPublicationPublishDouble(pubid[j], charging_voltage[j]) logger.debug(f'\tPublishing charging voltage of {charging_voltage[j]} ' f' at time {grantedtime}') # Send message to Controller with SOC every 15 minutes if grantedtime % 900 == 0: destination_name = str( h.helicsEndpointGetDefaultDestination(endid[j])) h.helicsEndpointSendBytesTo(endid[j], "", f'{currentsoc[j]:4f}'.encode( )) # logger.debug(f'Sent message from endpoint {endpoint_name}' f' at time {grantedtime}' f' with payload SOC {currentsoc[j]:4f}') # Calculate the total power required by all chargers. This is the # primary metric of interest, to understand the power profile # and capacity requirements required for this charging garage. total_power = 0 #logger.debug(f'Calculating charging power') for j in range(0,pub_count): charging_power = charge_rate[(EVlist[j]-1)] total_power += charging_power #logger.debug(f'\tCharging power in kW for EV{j+1}: {charging_power}')
source = h.helicsMessageGetOriginalSource(msg) logger.debug(f'Received message from endpoint {source}' f' at time {grantedtime}' f' with SOC {currentsoc}') # Send back charging command based on current SOC # Our very basic protocol: # If the SOC is less than soc_full keep charging (send "1") # Otherwise, stop charging (send "0") soc_full = 0.95 if float(currentsoc) <= soc_full: instructions = 1 else: instructions = 0 message = str(instructions) h.helicsEndpointSendBytesTo(endid, source, message.encode()) logger.debug(f'Sent message to endpoint {source}' f' at time {grantedtime}' f' with payload {instructions}') # Store SOC for later analysis/graphing if source not in soc: soc[source] = [] soc[source].append(float(currentsoc)) time_sim.append(grantedtime) # Since we've dealt with all the messages that are queued, there's # nothing else for the federate to do until/unless another # message comes in. Request a time very far into the future # and take a break until/unless a new message arrives.
logger.debug(f'\tNo messages at endpoint {endpoint_name} ' f'recieved at ' f'time {grantedtime}') # Publish updated charging voltage h.helicsPublicationPublishDouble(pubid[j], charging_voltage[j]) logger.debug( f'\tPublishing charging voltage of {charging_voltage[j]} ' f' at time {grantedtime}') # Send message to Controller with SOC every 15 minutes if grantedtime % 900 == 0: destination_name = str( h.helicsEndpointGetDefaultDestination(endid[j])) message = f'{currentsoc[j]:4f}' h.helicsEndpointSendBytesTo(endid[j], message.encode(), '') # logger.debug(f'Sent message from endpoint {endpoint_name}' f' to destination {destination_name}' f' at time {grantedtime}' f' with payload SOC {currentsoc[j]:4f}') # Calculate the total power required by all chargers. This is the # primary metric of interest, to understand the power profile # and capacity requirements required for this charging garage. total_power = 0 #logger.debug(f'Calculating charging power') for j in range(0, pub_count): charging_power = charge_rate[(EVlist[j] - 1)] total_power += charging_power #logger.debug(f'\tCharging power in kW for EV{j+1}: {charging_power}')