Source code for gym_anm.envs.anm6_env.rendering.py.rendering

import webbrowser
import json
import os
import requests
from websocket import create_connection
import time

from .servers import WsServer, HttpServer
from .constants import RENDERING_FOLDER, RENDERING_RELATIVE_PATH, RENDERING_LOGS


[docs]def start(title, dev_type, p_max, q_max, s_rate, v_magn_min, v_magn_max, soc_max, costs_range): """ Start visualizing the state of the environment in a new browser window. Parameters ---------- title : str The title to give to the visualization, usually the name of the environment. dev_type : list of int The type of each device connected to the network. p_max : list of float The maximum absolute real power injection of each device (MW). q_max : list of float The maximum absolute reactive power injection of each device (MVAr). s_rate : list of float The transmission line apparent power ratings (MVA). v_magn_min : list of float The minimum voltage magnitude allowed at each bus (pu). v_magn_max : list of float The maximum voltage magnitude allowed at each bus (pu). soc_max : list of float The maximum state of charge of each storage unit (MWh). costs_range : tuple of int The maximum absolute energy loss costs_clipping[0] and the maximum constraints violation penalty (parts of the reward function). Returns ------- http_server : HttpServer The HTTP server serving the visualization. ws_server : WsServer The WebSocket server used for message exchanges between the environment and the visualization. """ # Create log directory. if not os.path.exists(RENDERING_LOGS): os.makedirs(RENDERING_LOGS) # Initialize the servers. http_server = HttpServer() ws_server = WsServer() print("\n#######################") a = http_server.address + "/" + RENDERING_RELATIVE_PATH print("Rendering the environment at : " + a) print("#######################\n") # Write html file. write_html(ws_server.address) # Keep trying to connect to the websocket server (because it might not have # been fully initialized yet). Timeout after 15 seconds. timeout = time.time() + 15 while True: try: ws = create_connection(ws_server.address) break except ConnectionRefusedError as e: if time.time() > timeout: raise e # Open a new browser window to display the visualization. Keep trying until # the status page becomes == 200 (i.e., the server is running). Timeout after # 10 seconds. p = os.path.join(http_server.address, RENDERING_RELATIVE_PATH) timeout = time.time() + 10 while True: page = requests.get(p) if page.status_code == 200: break elif time.time() > timeout: raise ConnectionError("Connection to HTTP server timeout.") webbrowser.open(p) message = json.dumps( { "messageLabel": "init", "deviceType": dev_type, "pMax": p_max, "qMax": q_max, "sRate": s_rate, "vMagnMin": v_magn_min, "vMagnMax": v_magn_max, "socMax": soc_max, "energyLossMax": costs_range[0], "penaltyMax": costs_range[1], "title": title, }, separators=(",", ":"), ) ws.send(message) ws.close() return http_server, ws_server
[docs]def update(ws_address, cur_time, year_count, p, q, s, soc, p_potential, bus_v_magn, costs, network_collapsed): """ Update the visualization of the environment. Parameters ---------- ws_address : str The address of the listening WebSocket server. cur_time : datetime.datetime The time corresponding to the state of the network. year_count : int The number of full years passed since the last reset of the environment. p : list of float The real power injection from each device (MW). q : list of float The reactive power injection from each device (MVAr). s : list of float The apparent power flow in each branch (MVA). soc : list of float The state of charge of each storage unit (MWh). p_potential : list of float The potential real power generation of each VRE device before curtailment (MW). bus_v_magn : list of float The voltage magnitude of each bus (pu). costs : list of float The total energy loss and the total penalty associated with operating constraints violation. network_collapsed : bool True if no load flow solution is found (possibly infeasible); False otherwise. """ ws = create_connection(ws_address) time_array = [cur_time.month, cur_time.day, cur_time.hour, cur_time.minute] message = json.dumps( { "messageLabel": "update", "time": time_array, "yearCount": year_count, "pInjections": p, "qInjections": q, "sFlows": s, "socStorage": soc, "pPotential": p_potential, "vMagn": bus_v_magn, "reward": costs, "networkCollapsed": network_collapsed, } ) # Send the message. ws.send(message) ws.close() return
[docs]def close(http_server, ws_server): """ Terminate the parallel processes running the HTTP and WebSocket servers. Parameters ---------- http_server : HttpServer The HTTP server serving the visualization. ws_server : WsServer The WebSocket server used for message exchanges between the environment and the visualization. """ http_server.process.terminate() ws_server.process.terminate()
[docs]def write_html(address): """ Update the index.html file used for rendering the environment state. """ s = """<!DOCTYPE html> <html> <head> <link rel="stylesheet" href="css/styles.css"> <script>var wsServerAddress = "{}";</script> <script src="js/init.js"></script> <script src="js/devices.js"></script> <script src="js/graph.js"></script> <script src="js/dateTime.js"></script> <script src="js/reward.js"></script> <script src="js/text.js"></script> <script src="envs/anm6/svgLabels.js"></script> <title>gym-anm:ANM6</title> </head> <body onload="init();"> <header></header> <object id="svg-network" data="envs/anm6/network.svg" type="image/svg+xml" class="network"> </object> </body> </html> """.format( address ) html_file = os.path.join(RENDERING_FOLDER, "index.html") with open(html_file, "w") as f: f.write(s)