def essim_kpi_list(): ESSIM_config = settings.essim_config url = ESSIM_config['ESSIM_host'] + ESSIM_config[ 'ESSIM_path'] + '/kpiModules' try: r = requests.get(url) if r.status_code == 200: result = json.loads(r.text) # only communicate unique KPI-modules (because they are deployed multiple times) kpi_list = [] already_added_kpi_modules = [] for kpi in result: if not kpi[ "calculator_id"] in already_added_kpi_modules: kpi_list.append({ "id": kpi["calculator_id"], "name": kpi["title"], "descr": kpi["description"] }) already_added_kpi_modules.append( kpi["calculator_id"]) # store kpi_list in session, in order to look up name/descr in a later stage set_session('kpi_list', kpi_list) return json.dumps(kpi_list), 200 else: send_alert('Error in getting the ESSIM KPI list') abort(r.status_code, 'Error in getting the ESSIM KPI list') except Exception as e: send_alert('Error accessing ESSIM API: ' + str(e)) abort(500, 'Error accessing ESSIM API: ' + str(e))
def get_user_services_list(self, user: str, roles: List[str] = []) -> List[Dict[str, Any]]: """ Get the full list of services for this user with the given roles. Both user and roles come from Keycloak. """ srvs_list = self.get_user_settings(user) # store the user services list in session for later use set_session('services_list', srvs_list) # Start with user services, remove those services that the user does not have the role for. final_services_list = copy.deepcopy(srvs_list) for service in list(final_services_list): if "required_role" in service and service[ "required_role"] not in roles: final_services_list.remove(service) service_ids: List[str] = [ service["id"] for service in final_services_list ] # Get role based services and add them, unless a service with matching ID exists. role_based_services = self.get_role_based_services(roles) for role_based_service in role_based_services: if role_based_service["id"] not in service_ids: final_services_list.append(role_based_service) return final_services_list
def timedimension_initialize(info): """" This function is called when the user selects to use the TimeDimension functionality """ with self.flask_app.app_context(): database = info["database"] simulation_id = info["simulation_id"] networks = info["networks"] set_session('timedimension-database', database) set_session('timedimension-simulation-id', simulation_id) set_session( 'timedimension-parameter', 'allocationEnergy') # To be decided if configurable set_session('ielgas_monitor_ids', []) self.preprocess_data(networks) time_list = self.get_all_times_from_simulation() timedimension_colors = self.get_colors() set_session('timedimension-colors', timedimension_colors) # self.preload_simulation_data() # Return list of times. #return True return time_list
def view_modes_set_mode(mode): user = get_session('user-email') settings = self.get_user_settings(user) settings['mode'] = mode['mode'] self.set_user_settings(user, settings) set_session('mapeditor_view_mode', settings['mode']) logger.debug('User has MapEditor view mode: {}'.format( settings['mode']))
def ielgas_monitor_asset(info): asset_id = info['id'] ielgas_monitor_ids = get_session('ielgas_monitor_ids') if asset_id in ielgas_monitor_ids: ielgas_monitor_ids.remove(asset_id) else: ielgas_monitor_ids.append(asset_id) set_session('ielgas_monitor_ids', ielgas_monitor_ids)
def create_area_info_geojson(area): area_list = [] pot_list = [] shape_dictionary = get_session('shape_dictionary') if not shape_dictionary: shape_dictionary = {} print("- Finding ESDL boundaries...") BoundaryService.get_instance().preload_area_subboundaries_in_cache(area) find_area_info_geojson(area_list, pot_list, area, shape_dictionary) print("- Done") set_session('shape_dictionary', shape_dictionary) return area_list, pot_list
def essim_sensitivity_next_simulation(): time.sleep(1) sensitivity_analysis = get_session('sensitivity_analysis') if sensitivity_analysis: sensitivity_info = sensitivity_analysis['info'] sa_mutations = sensitivity_analysis['mutations'] sa_index = sensitivity_analysis['index'] sim_period_start = sensitivity_analysis['sim_period_start'] sim_period_end = sensitivity_analysis['sim_period_end'] sa_index = sa_index + 1 if sa_index == len(sa_mutations): del_session('sensitivity_analysis') return 0 # end of sensitivity analysis var_list = sa_mutations[sa_index] sim_title = '' for v in var_list: asset_id = v['asset_id'] attr = v['attr'] value = v['value'] obj, attr_name = self.get_obj_attr_name(asset_id, attr) self.set_param(obj, attr_name, value) if sim_title != '': sim_title += ' & ' sim_title += attr_name + '=' + si_format(value, precision=2) selected_kpis = sensitivity_analysis['selected_kpis'] result = self.essim.run_simulation(sim_title, sim_period_start, sim_period_end, selected_kpis, False) if result: set_session('sensitivity_analysis', { 'index': sa_index, 'info': sensitivity_info, 'mutations': sa_mutations, 'sim_period_start': sim_period_start, 'sim_period_end': sim_period_end, 'selected_kpis': selected_kpis }) return result else: return 0
def preprocess_area(self, area): user = get_session('user-email') year = self.boundary_service_instance.get_user_setting(user, 'boundaries_year') sub_area_shape_list = list() top_area_shape = list() if year and area.id and area.scope.name != 'UNDEFINED': if is_valid_boundary_id(area.id): boundary = self.boundary_service_instance.get_boundary_from_service(year, area.scope, str.upper(area.id)) top_area_shape = Shape.parse_geojson_geometry(boundary['geom']) for ar in area.area: if ar.id and ar.scope.name != 'UNDEFINED': if is_valid_boundary_id(ar.id): boundary = self.boundary_service_instance.get_boundary_from_service(year, ar.scope, str.upper(ar.id)) self.add_boundary_to_shape_list(sub_area_shape_list, ar.id, boundary) set_session('sub_area_shape_list', sub_area_shape_list) set_session('top_area_shape', top_area_shape) return len(sub_area_shape_list)
def essim_sensitivity_run_simulations(sim_info): sim_period_start = sim_info['period']['start'] sim_period_end = sim_info['period']['end'] selected_kpis = sim_info['selected_kpis'] del_session('kpi_result_list') # Clear list of KPI sensitivity_info = sim_info['sens_anal_info'] sa_mutations = list() var_list = list() self.get_sa_mutations(sensitivity_info, sa_mutations, var_list) logger.info('Starting sensitivity analysis with {} mutations'.format(len(sa_mutations))) sa_index = 0 var_list = sa_mutations[sa_index] sim_title = '' for v in var_list: asset_id = v['asset_id'] attr = v['attr'] value = v['value'] obj, attr_name = self.get_obj_attr_name(asset_id, attr) self.set_param(obj, attr_name, value) if sim_title != '': sim_title += ' & ' sim_title += attr_name + '=' + si_format(value, precision=2) result = self.essim.run_simulation(sim_title, sim_period_start, sim_period_end, selected_kpis, False) if result: set_session('sensitivity_analysis', { 'index': sa_index, 'info': sensitivity_info, 'mutations': sa_mutations, 'sim_period_start': sim_period_start, 'sim_period_end': sim_period_end, 'selected_kpis': selected_kpis }) else: del_session('sensitivity_analysis') return result
def socketio_esdldrive_open(message): with self.flask_app.app_context(): path = message['path'] token = get_session('jwt-token') uri = ESDLDriveHttpURI( url + resource_endpoint + path, headers_function=add_authorization_header) logger.debug('ESDLDrive open: {} ({})'.format( message, uri.plain)) esh = get_handler() try: es = esh.load_file(uri) except Exception as e: logger.error("Error in loading file from ESDLDrive: " + str(e)) #send_alert('Error loading ESDL file with id {} from store'.format(store_id)) return if es.name: title = drive_name + ': ' + es.name else: title = drive_name + ' ES id: ' + es.id set_session('active_es_id', es.id) set_session('es_filename', title) # TODO: separate filename and title es_info_list = {} set_session("es_info_list", es_info_list) emit('clear_ui') emit('clear_esdl_layer_list') self.executor.submit(process_energy_system, esh, None, title) # run in seperate thread
def set_simulation_id(sim_id): with self.flask_app.app_context(): esh = get_handler() print('Set ESSIM simulationRun ID: ' + sim_id) set_session('simulationRun', sim_id) ESSIM_config = settings.essim_config url = ESSIM_config['ESSIM_host'] + ESSIM_config[ 'ESSIM_path'] + '/' + sim_id try: r = requests.get(url) if r.status_code == 200: result = json.loads(r.text) active_simulation = { 'sim_id': sim_id, 'scenarioID': result['scenarioID'], 'simulationDescription': result['simulationDescription'], 'startDate': result['startDate'], 'endDate': result['endDate'], 'dashboardURL': result['dashboardURL'] } set_session('active_simulation', active_simulation) esdlstr_base64 = result['esdlContents'] esdlstr_base64_bytes = esdlstr_base64.encode('ascii') esdlstr_bytes = base64.decodebytes( esdlstr_base64_bytes) esdlstr = esdlstr_bytes.decode('ascii') res_es = esh.add_from_string(name=str(uuid.uuid4()), esdl_string=esdlstr) set_session('active_es_id', res_es.id) sdt = datetime.strptime(result['startDate'], '%Y-%m-%dT%H:%M:%S%z') edt = datetime.strptime(result['endDate'], '%Y-%m-%dT%H:%M:%S%z') influxdb_startdate = sdt.strftime('%Y-%m-%dT%H:%M:%SZ') influxdb_enddate = edt.strftime('%Y-%m-%dT%H:%M:%SZ') # Call init_simulation to enable the loadflow calculations self.essim_kpis.init_simulation( res_es, sim_id, influxdb_startdate, influxdb_enddate) self.executor.submit(process_energy_system, esh, 'test') # run in seperate thread except Exception as e: # print('Exception: ') # print(e) send_alert('Error accessing ESSIM API: ' + str(e))
def socketio_esdldrive_open(message): with self.flask_app.app_context(): path = message['path'] params = dict() import_es = False if 'revision' in message: params['revision'] = message['revision'] if 'nocache' in message: params['nocache'] = message['nocache'] if 'import' in message: import_es = message['import'] logger.debug("Open params: {}".format(params)) #token = get_session('jwt-token') uri = ESDLDriveHttpURI( url + resource_endpoint + path, headers_function=add_authorization_header, getparams=params) logger.debug('ESDLDrive open: {} ({})'.format( message, uri.plain)) esh = get_handler() try: if import_es: es, parse_info = esh.import_file(uri) else: es, parse_info = esh.load_file(uri) if len(parse_info) > 0: info = '' for line in parse_info: info += line + "\n" message = "Warnings while opening {}:\n\n{}".format( uri.last_segment, info) emit('alert', message, namespace='/esdl') print(esh.rset.resources) except Exception as e: logger.error("Error in loading file from ESDLDrive: " + str(e)) return if hasattr(es, 'name') and es.name: title = drive_name + ': ' + es.name else: title = drive_name + ' ES id: ' + es.id set_session('active_es_id', es.id) set_session( 'es_filename', uri.last_segment) # TODO: separate filename and title es_info_list = {} set_session("es_info_list", es_info_list) emit('clear_ui') emit('clear_esdl_layer_list') self.executor.submit(process_energy_system, esh, uri.last_segment, title) # run in seperate thread
def preprocess_data(self, networks): influxdb_client = self.connect_to_database() # Figure out all the time stamps. determine_networks_automatically = True networks_list = list() if len(networks): networks_list = networks determine_networks_automatically = False asset_ids = dict() logger.debug("finding all IDs from assets") query = "SHOW TAG VALUES WITH KEY=\"assetId\"" result = influxdb_client.query(query) if result: for key in list(result.keys()): # Create list of networks if determine_networks_automatically: networks_list.append(key[0]) # Create list of assetIds per network asset_list = list() for kv in result[key]: asset_list.append(kv["value"]) asset_ids[key[0]] = asset_list set_session('timedimension-networks-list', networks_list) set_session('timedimension-asset-ids', asset_ids) logger.debug("calculating min/max per carrier") allocation_boundaries = dict() simulation_parameter = get_session('timedimension-parameter') query = "SELECT MIN({}), MAX({}) FROM {}".format( simulation_parameter, simulation_parameter, ",".join(networks_list)) result = allocation_energy = influxdb_client.query(query) if result: for key in list(allocation_energy.keys()): series = allocation_energy[key] for item in series: allocation_boundaries[key] = (item['min'], item['max']) logger.debug(allocation_boundaries) set_session('timedimension-allocation-boundaries', allocation_boundaries)
def get_boundary_info(info): print('get_boundary_info:') print(info) user = get_session('user-email') user_settings = self.get_user_settings(user) boundaries_year = user_settings['boundaries_year'] shape_dictionary = get_session('shape_dictionary') if not shape_dictionary: shape_dictionary = {} identifier = info["identifier"] toparea_name = info["toparea_name"] scope = info["scope"] subscope_enabled = info["subscope_enabled"] subscope = info["subscope"] select_subareas = info["select_subareas"] selected_subareas = info["selected_subareas"] initialize_ES = info["initialize_ES"] add_boundary_to_ESDL = info["add_boundary_to_ESDL"] if not is_valid_boundary_id(identifier): send_alert( "Not a valid identifier. Try identifiers like PV27 (Noord-Holland) or GM0060 (Ameland)" ) return active_es_id = get_session('active_es_id') esh = get_handler() es_edit = esh.get_energy_system(es_id=active_es_id) instance = es_edit.instance area = instance[0].area area_list = [] boundary = None if subscope_enabled: self.__preload_subboundaries_in_cache( boundaries_year, esdl.AreaScopeEnum.from_string(str.upper(scope)), esdl.AreaScopeEnum.from_string(str.upper(subscope)), str.upper(identifier)) else: boundary = self.get_boundary_from_service( boundaries_year, esdl.AreaScopeEnum.from_string(str.upper(scope)), str.upper(identifier)) if boundary: geom = boundary['geom'] # geometry = ESDLGeometry.create_geometry_from_geom() shape = Shape.parse_geojson_geometry(boundary['geom']) if shape: shape_dictionary[identifier] = shape for i in range(0, len(geom['coordinates'])): if len(geom['coordinates']) > 1: area_id_number = " ({} of {})".format( i + 1, len(geom['coordinates'])) else: area_id_number = "" area_list.append({ "type": "Feature", "geometry": { "type": "Polygon", "coordinates": geom['coordinates'][i] }, "properties": { "id": area.id + area_id_number, "name": area.name, "KPIs": [] } }) if initialize_ES: # change ID, name and scope of ES if select_subareas: area.id = "part of " + identifier else: area.id = identifier # Area ID has changed, re-add to dictionairy esh.add_object_to_dict(active_es_id, area) area.scope = esdl.AreaScopeEnum.from_string(str.upper(scope)) area.name = toparea_name if add_boundary_to_ESDL: # returns boundary: { type: '', boundary: [[[[ ... ]]]] } (multipolygon in RD) if not boundary: # check if already requested boundary = self.get_boundary_from_service( boundaries_year, esdl.AreaScopeEnum.from_string(str.upper(scope)), str.upper(identifier)) if boundary: geometry = ESDLGeometry.create_geometry_from_geom( boundary['geom']) area.geometry = geometry shape = Shape.parse_geojson_geometry(boundary['geom']) if shape: shape_dictionary[identifier] = shape # boundary = get_boundary_from_service(area_scope, area_id) # if boundary: # emit('area_boundary', {'info-type': 'MP-RD', 'crs': 'RD', 'boundary': boundary}) if subscope_enabled: boundaries = self.__get_subboundaries_from_service( boundaries_year, esdl.AreaScopeEnum.from_string(str.upper(scope)), esdl.AreaScopeEnum.from_string(str.upper(subscope)), str.upper(identifier)) # result (boundaries) is an ARRAY of: # {'code': 'BU00140500', 'geom': '{"type":"MultiPolygon","bbox":[...],"coordinates":[[[[6.583651,53.209594], # [6.58477,...,53.208816],[6.583651,53.209594]]]]}'} if not boundaries: send_alert( 'Error processing boundary information or no boundary information returned' ) for boundary in boundaries: geom = None try: # geom = json.loads(boundary["geom"]) geom = boundary["geom"] shape = Shape.parse_geojson_geometry(boundary['geom']) if shape: shape_dictionary[boundary['code']] = shape except Exception as e: print( 'Error parsing JSON from GEIS boundary service: ' + str(e)) if geom: skip_subarea = False if select_subareas and selected_subareas and boundary[ "code"] not in selected_subareas: skip_subarea = True if not skip_subarea: sub_area_id = boundary["code"] sub_area_name = boundary["name"] if initialize_ES: sub_area = esdl.Area() sub_area.id = sub_area_id sub_area.name = sub_area_name sub_area.scope = esdl.AreaScopeEnum.from_string( str.upper(subscope)) if add_boundary_to_ESDL: geometry = ESDLGeometry.create_geometry_from_geom( geom) sub_area.geometry = geometry area.area.append(sub_area) esh.add_object_to_dict(active_es_id, sub_area) for i in range(0, len(geom['coordinates'])): if len(geom['coordinates']) > 1: area_id_number = " ({} of {})".format( i + 1, len(geom['coordinates'])) else: area_id_number = "" area_list.append({ "type": "Feature", "geometry": { "type": "Polygon", "coordinates": geom['coordinates'][i] }, "properties": { "id": sub_area_id + area_id_number, "name": sub_area_name, "KPIs": [] } }) set_session('shape_dictionary', shape_dictionary) emit('geojson', {"layer": "area_layer", "geojson": area_list}) print('Ready processing boundary information')
def initialize_boundary_service_extension(): user = get_session('user-email') user_settings = self.get_user_settings(user) set_session('boundary_service_settings', user_settings)
def clear_mapeditor_ui(self): es_info_list = {} set_session("es_info_list", es_info_list) emit('clear_ui') emit('clear_esdl_layer_list')
def process_energy_system(esh, filename=None, es_title=None, app_context=None, force_update_es_id=None, zoom=True): # emit('clear_ui') print("Processing energysystems in esh") print("active_es_id at start: {}".format(get_session('active_es_id'))) # 4 June 2020 - Edwin: uncommented following line, we need to check if this is now handled properly # set_session('active_es_id', main_es.id) # TODO: check if required here? es_list = esh.get_energy_systems() es_info_list = get_session("es_info_list") if force_update_es_id == "all": emit('clear_esdl_layer_list') for es in es_list: asset_list = [] building_list = [] area_bld_list = [] conn_list = [] if not isinstance(es, esdl.EnergySystem): print( "- Detected ESDL without an EnergySystem, is of type {}. Ignoring." .format(es.eClass.name)) continue if es.id is None: es.id = str(uuid.uuid4()) if es.id not in es_info_list or es.id == force_update_es_id or force_update_es_id == "all": print("- Processing energysystem with id {}".format(es.id)) name = es.name if not name: title = 'Untitled Energysystem' else: title = name emit('create_new_esdl_layer', { 'es_id': es.id, 'title': title }) # removes old layer if exists emit('set_active_layer_id', es.id) area = es.instance[0].area find_boundaries_in_ESDL( area) # also adds coordinates to assets if possible carrier_list = ESDLEnergySystem.get_carrier_list(es) emit('carrier_list', { 'es_id': es.id, 'carrier_list': carrier_list }) sector_list = ESDLEnergySystem.get_sector_list(es) if sector_list: emit('sector_list', { 'es_id': es.id, 'sector_list': sector_list }) # KPIs that are connected to top-level area are visualized in a KPI dialog print('- Processing KPIs') area_kpis = ESDLEnergySystem.process_area_KPIs(area) area_name = area.name if not area_name: area_name = title if area_kpis: emit('kpis', { 'es_id': es.id, 'scope': area_name, 'kpi_list': area_kpis }) # measures can contain assets that still need to be added to the energysystem assets_to_be_added = AssetsToBeAdded.get_assets_from_measures(es) if assets_to_be_added: emit('ATBA_assets_to_be_added', { 'ed_id': es.id, 'assets_to_be_added': assets_to_be_added }) # Probably the following call is not required anymore, everything is handled by find_boundaries_in_ESDL add_missing_coordinates(area) print('- Processing area') process_area(esh, es.id, asset_list, building_list, area_bld_list, conn_list, area, 0) notes_list = get_notes_list(es) emit('add_building_objects', { 'es_id': es.id, 'building_list': building_list, 'zoom': zoom }) emit('add_esdl_objects', { 'es_id': es.id, 'asset_pot_list': asset_list, 'zoom': zoom }) emit('area_bld_list', { 'es_id': es.id, 'area_bld_list': area_bld_list }) emit('add_connections', { 'es_id': es.id, 'add_to_building': False, 'conn_list': conn_list }) emit('add_notes', {'es_id': es.id, 'notes_list': notes_list}) set_session_for_esid(es.id, 'conn_list', conn_list) set_session_for_esid(es.id, 'asset_list', asset_list) set_session_for_esid(es.id, 'area_bld_list', area_bld_list) # TODO: update asset_list??? es_info_list[es.id] = {"processed": True} # If one energysystem is added (by calling an external service or via the API) the active_es_id (backend) and # active_layer_id (frontend) are not synchronized. As a temporary fix the following lines are added. # Be aware: process_energy_system is called in a seperate thread, active_es_id is also changed in the functions # calling process_energy_system! if get_session('active_es_id') != es.id: set_session('active_es_id', es.id) else: print("- Energysystem with id {} already processed".format(es.id)) set_handler(esh) # emit('set_active_layer_id', main_es.id) print("active_es_id at end: {}".format(get_session('active_es_id'))) #session.modified = True print('session variables set', session)
def initialize_user(self, user): settings = self.get_user_settings(user) set_session('mapeditor_view_mode', settings['mode']) logger.debug('User has MapEditor view mode: {}'.format( settings['mode'])) return settings['mode']
def timedimension_initialize(): set_session('ielgas_monitor_ids', []) self.preprocess_data() # self.preload_simulation_data() return True
def get_simulation_progress(): with self.flask_app.app_context(): es_simid = get_session('es_simid') user_email = get_session('user-email') # print(es_simid) if es_simid: active_simulation = get_session('active_simulation') ESSIM_config = settings.essim_config if active_simulation['essim_loadflow']: url = ESSIM_config[ 'ESSIM_host_loadflow'] + ESSIM_config[ 'ESSIM_path'] + '/' + es_simid else: url = ESSIM_config['ESSIM_host'] + ESSIM_config[ 'ESSIM_path'] + '/' + es_simid try: r = requests.get(url + '/status') if r.status_code == 200: result = json.loads(r.text) status = result["status"] if "moreInfo" in result: more_info = result["moreInfo"] else: more_info = "" if status == -1: descr = result["description"] return (jsonify({ 'percentage': '-1', 'url': '', 'simulationRun': es_simid, 'description': descr, 'moreInfo': more_info })), 200 if float(status) >= 1: r = requests.get(url) if r.status_code == 200: # del_session('es_simid') # simulation ready result = json.loads(r.text) dashboardURL = result['dashboardURL'] # Update the stored simulation with the dashboard URL active_simulation = get_session( 'active_simulation') active_simulation[ 'dashboardURL'] = dashboardURL set_session('simulationRun', es_simid) self.update_stored_simulation( user_email, es_simid, 'dashboard_url', dashboardURL) # Initialize the essim kpi class instance, to be able to show load duration curves esh = get_handler() active_es_id = get_session('active_es_id') current_es = esh.get_energy_system( es_id=active_es_id) sdt = datetime.strptime( active_simulation['startDate'], '%Y-%m-%dT%H:%M:%S%z') edt = datetime.strptime( active_simulation['endDate'], '%Y-%m-%dT%H:%M:%S%z') influxdb_startdate = sdt.strftime( '%Y-%m-%dT%H:%M:%SZ') influxdb_enddate = edt.strftime( '%Y-%m-%dT%H:%M:%SZ') self.essim_kpis.init_simulation( current_es, es_simid, influxdb_startdate, influxdb_enddate) return (jsonify({ 'percentage': '1', 'url': dashboardURL, 'simulationRun': es_simid })), 200 else: send_alert( 'Error in getting the ESSIM dashboard URL' ) abort( r.status_code, 'Error in getting the ESSIM dashboard URL' ) else: return (jsonify({ 'percentage': status, 'url': '', 'simulationRun': es_simid })), 200 else: # print('code: ', r.status_code) send_alert( 'Error in getting the ESSIM progress status') abort( r.status_code, 'Error in getting the ESSIM progress status') except Exception as e: # print('Exception: ') # print(e) send_alert('Error accessing ESSIM API: ' + str(e)) abort(500, 'Error accessing ESSIM API: ' + str(e)) else: print( "ERROR: Querying simulation progress - No es_simid in session" ) print(session) abort(500, 'Simulation not running')
def process_kpi_results(self, kpi_result_array): kpis_this_sim_run = [] one_still_calculating = False kpi_list = get_session('kpi_list') # contains id, name and description for kpi_result_item in kpi_result_array: kpi_id = list(kpi_result_item.keys())[0] kpi_result = kpi_result_item[kpi_id] kpi_info = dict() kpi_info['id'] = kpi_id kpi_info['name'] = None kpi_info['descr'] = None for kpi in kpi_list: if kpi['id'] == kpi_id: kpi_info['name'] = kpi['name'] kpi_info['descr'] = kpi['descr'] kpi_info['calc_status'] = kpi_result['status'] if kpi_info['calc_status'] == 'Not yet started': one_still_calculating = True if kpi_info['calc_status'] == 'Calculating': kpi_info['progress'] = kpi_result['progress'] one_still_calculating = True if kpi_info['calc_status'] == 'Success': kpi_info['kpi'] = kpi_result['kpi'] if 'unit' in kpi_info: kpi_info['unit'] = kpi_result['unit'] kpis_this_sim_run.append(kpi_info) simid = get_session('es_simid') active_es_id = get_session('active_es_id') kpi_result_list = get_session('kpi_result_list') if kpi_result_list: kpis_per_simid = kpi_result_list["kpis_per_simid"] if active_es_id != kpi_result_list[ "es_id"]: # if this is a simulation of a new energy system kpis_per_simid = dict() # start with an empty dict kpi_result_list[ "es_id"] = active_es_id # set the current es_id kpis_per_simid[ simid] = kpis_this_sim_run # add the kpis of the last simulation run else: kpi_result_list = dict() # first KPIs for the energy system kpi_result_list["es_id"] = active_es_id kpi_result_list["kpis_per_simid"] = dict() kpi_result_list["kpis_per_simid"][simid] = kpis_this_sim_run result = { 'still_calculating': one_still_calculating, 'results': kpis_this_sim_run } # print("Processed results (sent back to client):") # print(result) if not one_still_calculating: # self.emit_kpis_for_visualization(kpi_result_list) print("All KPIs finished calculation") set_session('kpi_result_list', kpi_result_list) user_email = get_session('user-email') # TODO: fix storing per simid self.update_stored_simulation(user_email, simid, 'kpi_result_list', kpi_result_list) return result
def run_simulation(self, sim_description, sim_start_datetime, sim_end_datetime, essim_kpis, essim_loadflow): with self.flask_app.app_context(): # Clear current active session information del_session('active_simulation') del_session('es_simid') esh = get_handler() active_es_id = get_session('active_es_id') user_email = get_session('user-email') user_fullname = get_session('user-fullname') if user_fullname is None: user_fullname = 'essim' current_es = esh.get_energy_system(es_id=active_es_id) current_es_name = current_es.name if current_es_name == "": current_es_name = "Untitled energysystem" esdlstr = esh.to_string(active_es_id) esdlstr_bytes = esdlstr.encode('ascii') esdlstr_base64_bytes = base64.b64encode(esdlstr_bytes) esdlstr_base64 = esdlstr_base64_bytes.decode('ascii') ESSIM_config = settings.essim_config print("essim_loadflow: {}".format(essim_loadflow)) if essim_loadflow: url = ESSIM_config['ESSIM_host_loadflow'] + ESSIM_config[ 'ESSIM_path'] else: url = ESSIM_config['ESSIM_host'] + ESSIM_config['ESSIM_path'] # print('ESSIM url: ', url) payload = { 'user': user_fullname.strip(), 'scenarioID': active_es_id, 'simulationDescription': sim_description, 'startDate': sim_start_datetime, 'endDate': sim_end_datetime, 'influxURL': ESSIM_config['influxURL'], # 'grafanaURL': ESSIM_config['grafanaURL'], # 'esdlContents': urllib.parse.quote(esdlstr) 'esdlContents': esdlstr_base64 } if essim_kpis: kpi_module = { # 'kafkaURL': ESSIM_config['kafka_url'], 'modules': [] } # payload['kafkaURL'] = ESSIM_config['kafka_url'] payload['natsURL'] = ESSIM_config['natsURL'] # TODO: Fix hard-coded TimeResolution = hourly for kpi_id in essim_kpis: kpi_module['modules'].append({ 'id': kpi_id, 'config': { 'TimeResolution': 'yearly' } # 'config': [{'key': 'TimeResolution', 'value': 'hourly'}] }) payload['kpiModule'] = kpi_module # print(payload) headers = { 'Content-Type': "application/json", 'Accept': "application/json", 'User-Agent': "ESDL Mapeditor/0.1" # 'Cache-Control': "no-cache", # 'Host': ESSIM_config['ESSIM_host'], # 'accept-encoding': "gzip, deflate", # 'Connection': "keep-alive", # 'cache-control': "no-cache" } try: r = requests.post(url, json=payload, headers=headers) # print(r) # print(r.content) if r.status_code == 201: result = json.loads(r.text) sim_id = result['id'] set_session('es_simid', sim_id) print("ESSIM started, sim_id: " + sim_id) self.store_simulation( user_email, sim_id, datetime.now().strftime("%Y-%m-%d %H:%M:%S"), sim_description, current_es_name) # emit('', {}) active_simulation = { 'sim_id': sim_id, 'scenarioID': active_es_id, 'simulationDescription': sim_description, 'startDate': sim_start_datetime, 'endDate': sim_end_datetime, 'dashboardURL': '', 'kpi_result_list': None, 'essim_loadflow': essim_loadflow } set_session('active_simulation', active_simulation) else: send_alert('Error starting ESSIM simulation - response ' + str(r.status_code) + ' with reason: ' + str(r.reason)) print('Error starting ESSIM simulation - response ' + str(r.status_code) + ' with reason: ' + str(r.reason)) print(r.content) # emit('', {}) return 0 except Exception as e: print('Error accessing ESSIM API at starting: ' + str(e)) send_alert('Error accessing ESSIM API at starting: ' + str(e)) return 0 return 1