def add_asset_to_asset_list(asset_list, asset): port_list = [] ports = asset.port for p in ports: conn_to_ids = [cp.id for cp in p.connectedTo] profile = p.profile profile_info_list = [] p_carr_id = None if p.carrier: p_carr_id = p.carrier.id if profile: profile_info_list = [] # generate_profile_info(profile) port_list.append({ 'name': p.name, 'id': p.id, 'type': type(p).__name__, 'conn_to': conn_to_ids, 'profile': profile_info_list, 'carrier': p_carr_id }) state = asset_state_to_ui(asset) geom = asset.geometry if geom: if isinstance(geom, esdl.Point): lat = geom.lat lon = geom.lon capability_type = ESDLAsset.get_asset_capability_type(asset) attrs = get_tooltip_asset_attrs(asset, 'marker') add_spatial_attributes(asset, attrs) asset_list.append([ 'point', 'asset', asset.name, asset.id, type(asset).__name__, [lat, lon], attrs, state, port_list, capability_type ]) if isinstance(geom, esdl.Line): coords = [] for point in geom.point: coords.append([point.lat, point.lon]) attrs = get_tooltip_asset_attrs(asset, 'line') add_spatial_attributes(asset, attrs) asset_list.append([ 'line', 'asset', asset.name, asset.id, type(asset).__name__, coords, attrs, state, port_list ]) if isinstance(geom, esdl.Polygon): coords = ESDLGeometry.parse_esdl_subpolygon(geom.exterior, False) # [lon, lat] coords = ESDLGeometry.exchange_coordinates( coords) # --> [lat, lon] capability_type = ESDLAsset.get_asset_capability_type(asset) attrs = get_tooltip_asset_attrs(asset, 'polygon') add_spatial_attributes(asset, attrs) asset_list.append([ 'polygon', 'asset', asset.name, asset.id, type(asset).__name__, coords, attrs, state, port_list, capability_type ])
def add_asset_and_emit(self, esh: EnergySystemHandler, es_id: str, asset: EnergyAsset, area_bld_id: str): with self.flask_app.app_context(): asset_to_be_added_list = list() port_list = self.calculate_port_list(asset) message = self.create_asset_discription_message(asset, port_list) asset_to_be_added_list.append(message) if not ESDLAsset.add_object_to_area(esh.get_energy_system(es_id), asset, area_bld_id): ESDLAsset.add_object_to_building(esh.get_energy_system(es_id), asset, area_bld_id) emit('add_esdl_objects', {'es_id': es_id, 'asset_pot_list': asset_to_be_added_list, 'zoom': False}, namespace='/esdl')
def energy_asset_to_ui(esh, es_id, asset): # , port_asset_mapping): port_list = [] conn_list = [] ports = asset.port for p in ports: # p_asset = port_asset_mapping[p.id] p_asset = get_asset_and_coord_from_port_id(esh, es_id, p.id) p_asset_coord = p_asset['coord'] # get proper coordinate if asset is line conn_to = [cp.id for cp in p.connectedTo] profile = p.profile profile_info_list = [] if profile: profile_info_list = generate_profile_info(profile) port_list.append \ ({'name': p.name, 'id': p.id, 'type': type(p).__name__, 'conn_to': conn_to, 'profile': profile_info_list}) if conn_to: # conn_to_list = conn_to.split(' ') # connectedTo attribute is list of port ID's separated by a space for id in conn_to: # pc_asset = port_asset_mapping[id] pc_asset = get_asset_and_coord_from_port_id(esh, es_id, id) pc_asset_coord = pc_asset['coord'] conn_list.append \ ({'from-port-id': p.id, 'from-asset-id': p_asset['asset'].id, 'from-asset-coord': p_asset_coord, 'to-port-id': id, 'to-asset-id': pc_asset['asset'].id, 'to-asset-coord': pc_asset_coord}) geom = asset.geometry if geom: if isinstance(geom, esdl.Point): lat = geom.lat lon = geom.lon capability_type = ESDLAsset.get_asset_capability_type(asset) return ['point', 'asset', asset.name, asset.id, type(asset).__name__, [lat, lon], port_list, capability_type], conn_list elif isinstance(geom, esdl.Line): coords = [] for point in geom.point: coords.append([point.lat, point.lon]) return ['line', 'asset', asset.name, asset.id, type(asset).__name__, coords, port_list], conn_list elif isinstance(geom, esdl.Polygon): if isinstance(asset, esdl.WindParc) or isinstance(asset, esdl.PVParc) or isinstance(asset, esdl.WindPark) \ or isinstance(asset, esdl.PVPark): coords = ESDLGeometry.parse_esdl_subpolygon(geom.exterior, False) # [lon, lat] coords = ESDLGeometry.exchange_coordinates(coords) # --> [lat, lon] capability_type = ESDLAsset.get_asset_capability_type(asset) # print(coords) return ['polygon', 'asset', asset.name, asset.id, type(asset).__name__, coords, port_list, capability_type], conn_list else: return [], []
def get_edr_vesta_measures(self, measures_id): url = self.vesta_plugin_settings[ "edr_url"] + "/store/esdl/" + measures_id + "?format=xml" try: r = requests.get(url) if r.status_code == 200: result = [] self.selected_measures = ESDLAsset.load_asset_from_string( r.text) for m in self.selected_measures.measure: result.append({"id": m.id, "name": m.name}) return result else: print( 'EDR returned unexpected result. Check Vesta plugin settings' ) send_alert( 'EDR returned unexpected result. Check Vesta plugin settings' ) return None except Exception as e: print('Error accessing EDR API: ' + str(e)) send_alert('Error accessing EDR API: ' + str(e)) return None
def get_bag_contours(info): with self.flask_app.app_context(): print("getting bag information") esh = get_handler() active_es_id = get_session('active_es_id') area_id = info["id"] area_polygon = { 'type': 'polygon', 'coordinates': info["polygon"] } geometry = ESDLGeometry.create_ESDL_geometry(area_polygon) boundary_wgs = ESDLGeometry.create_boundary_from_geometry(geometry) # boundary_geojson = ESDLGeometry.create_geojson(area_id, '', [], boundary_wgs) wkt_string = wkt.dumps(boundary_wgs) # wkt_string = 'POLYGON ((4.359093904495239 52.012174264626445, 4.357388019561768 52.01154692445308, 4.357978105545044 52.01078750089633, 4.360188245773315 52.01160635705717, 4.362355470657349 52.012478026181434, 4.360767602920532 52.012847820073766, 4.359093904495239 52.012174264626445))' # wkt_quoted = urllib.parse.quote(wkt_string) es_edit = esh.get_energy_system(es_id=active_es_id) instance = es_edit.instance top_area = instance[0].area target_area = ESDLEnergySystem.find_area(top_area, area_id) if target_area: try: # url = 'http://' + settings.bag_config["host"] + ':' + settings.bag_config["port"] + \ # settings.bag_config["path_contour"] + '?wkt=' + wkt_quoted + '&format=xml' # print(url) # r = requests.get(url) url = 'http://' + settings.bag_config["host"] + ':' + settings.bag_config["port"] + \ settings.bag_config["path_contour"] + '?format=xml' print(url) r = requests.post(url, json={"wkt": wkt_string}) if r.status_code == 201: esdl_string = r.text bag_es = ESDLAsset.load_asset_from_string(esdl_string) if bag_es: bag_inst = bag_es.instance[0] if bag_inst: bag_area = bag_inst.area if bag_area: bld_list = [] for bld in bag_area.asset: if isinstance(bld, esdl.Building): target_area.asset.append(bld.deepcopy()) geometry = bld.geometry boundary_wgs = ESDLGeometry.create_boundary_from_geometry(geometry) bld_list.append(ESDLGeometry.create_geojson(bld.id, bld.name, [], boundary_wgs)) if bld_list: emit('geojson', {"layer": "bld_layer", "geojson": bld_list}) except Exception as e: print('ERROR in accessing BAG service: '+str(e)) return None # @EWOUD: Deze 'mogelijkheid' kunnen we ook gebruiken om geometries te renderen in de frontend # self.emit_geometries_to_client(esh, active_es_id, bld_list) else: print("ERROR in finding area in ESDL for BAG service") # self.flask_app.send_alert("ERROR in finding area in ESDL for BAG service") return None
def create_asset_discription_message(asset: EnergyAsset, port_list): if isinstance(asset, AbstractConductor): # assume a Line geometry here coords = [(p.lat, p.lon) for p in asset.geometry.point] return ['line', 'asset', asset.name, asset.id, type(asset).__name__, coords, port_list] else: capability_type = ESDLAsset.get_asset_capability_type(asset) return ['point', 'asset', asset.name, asset.id, type(asset).__name__, asset.geometry.lat, asset.geometry.lon, port_list, capability_type]
def convert_potential(esh, active_es_id, pot, add_to_building, percentage, asset_list): pot_container = pot.eContainer() # Determine orientation from potential information orientation_name = "" if pot.orientation in PICO_ROOF_ORIENTATIONS: orientation_name = " (" + PICO_ROOF_ORIENTATIONS[pot.orientation] + ")" # Create a PVInstallation instance and attach a profile with the percentage of the potential that # will be 'installed' pv_installation = esdl.PVInstallation(id=str(uuid.uuid4()), name="PV Installation" + orientation_name) pv_outport = esdl.OutPort(id=str(uuid.uuid4()), name="Out") pv_profile = esdl.SingleValue(id=str(uuid.uuid4()), name="PV production", value=pot.value * percentage / 100) # Assume kWh for now, Geodan should communicate this in the ESDL in the end pv_profile.profileQuantityAndUnit = esdl.QuantityAndUnitType( physicalQuantity=esdl.PhysicalQuantityEnum.ENERGY, unit=esdl.UnitEnum.WATTHOUR, multiplier=esdl.MultiplierEnum.KILO) pv_outport.profile.append(pv_profile) pv_installation.port.append(pv_outport) # Generate a location on the map for the PV Installation if isinstance(pot_container, esdl.AbstractBuilding): # Place the Asset in the top left corner of the BuildingEditor pv_geometry = esdl.Point(lon=10.0, lat=490.0, CRS="Simple") pv_installation.geometry = pv_geometry add_to_building[0] = True else: pot_geometry = pot.geometry if isinstance(pot_geometry, esdl.Point): # Place the Asset with a small offset from the SolarPotential marker pv_geometry = esdl.Point(lon=pot_geometry.lon + 0.001, lat=pot_geometry.lat - 0.001) pv_installation.geometry = pv_geometry else: logger.warning('Using potentials with geometry other than esdl.Point not supported yet') # Add the PVInstallation to the same container as the SolarPotential (Area or Building) pot_container.asset.append(pv_installation) esh.add_object_to_dict(active_es_id, pv_installation, recursive=True) if isinstance(pot_container, esdl.AbstractBuilding): calc_building_assets_location(pot_container, True) # Adapt the potential (substract the installed value) pot.value = pot.value * (100-percentage) / 100 port_list = [{'name': pv_outport.name, 'id': pv_outport.id, 'type': type(pv_outport).__name__, 'conn_to': []}] capability_type = ESDLAsset.get_asset_capability_type(pv_installation) tooltip_asset_attrs = get_tooltip_asset_attrs(pv_installation, 'marker') asset_list.append(['point', 'asset', pv_installation.name, pv_installation.id, type(pv_installation).__name__, [pv_geometry.lat, pv_geometry.lon], tooltip_asset_attrs, 'e', port_list, capability_type]) return pv_installation
def create_asset_description_message(asset: EnergyAsset, port_list): state = asset_state_to_ui(asset) if isinstance(asset, AbstractConductor): # assume a Line geometry here coords = [(p.lat, p.lon) for p in asset.geometry.point] tooltip_asset_attrs = get_tooltip_asset_attrs(asset, 'line') add_spatial_attributes(asset, tooltip_asset_attrs) return [ 'line', 'asset', asset.name, asset.id, type(asset).__name__, coords, tooltip_asset_attrs, state, port_list ] else: capability_type = ESDLAsset.get_asset_capability_type(asset) tooltip_asset_attrs = get_tooltip_asset_attrs(asset, 'marker') add_spatial_attributes(asset, tooltip_asset_attrs) return [ 'point', 'asset', asset.name, asset.id, type(asset).__name__, [asset.geometry.lat, asset.geometry.lon], tooltip_asset_attrs, state, port_list, capability_type ]
def use_part_of_potential(pot_id, percentage): """ Use part of a SolarPotential to install a PVInstallation :param pot_id: id of the SolarPotential :param percentage: percentage (0-100) of the SolarPotential that should be installed as a PVInstallation :return: None """ with self.flask_app.app_context(): esh = get_handler() active_es_id = get_session('active_es_id') pot = esh.get_by_id(active_es_id, pot_id) pot_container = pot.eContainer() # Create a PVInstallation instance and attach a profile with the percentage of the potential that # will be 'installed' pv_installation = esdl.PVInstallation(id=str(uuid.uuid4()), name="PV Installation") pv_outport = esdl.OutPort(id=str(uuid.uuid4()), name="Out") pv_profile = esdl.SingleValue(id=str(uuid.uuid4()), name="PV production", value=pot.value * percentage / 100) # Assume kWh for now, Geodan should communicate this in the ESDL in the end pv_profile.profileQuantityAndUnit = esdl.QuantityAndUnitType( physicalQuantity=esdl.PhysicalQuantityEnum.ENERGY, unit=esdl.UnitEnum.WATTHOUR, multiplier=esdl.MultiplierEnum.KILO) pv_outport.profile.append(pv_profile) pv_installation.port.append(pv_outport) add_to_building = False # Generate a location on the map for the PV Installation if isinstance(pot_container, esdl.AbstractBuilding): # Place the Asset in the top left corner of the BuildingEditor pv_geometry = esdl.Point(lon=10, lat=490, CRS="Simple") pv_installation.geometry = pv_geometry add_to_building = True else: pot_geometry = pot.geometry if isinstance(pot_geometry, esdl.Point): # Place the Asset with a small offset from the SolarPotential marker pv_geometry = esdl.Point(lon=pot_geometry.lon + 0.001, lat=pot_geometry.lat - 0.001) pv_installation.geometry = pv_geometry else: logger.warning( 'Using potentials with geometry other than esdl.Point not supported yet' ) # Add the PVInstallation to the same container as the SolarPotential (Area or Building) pot_container.asset.append(pv_installation) esh.add_object_to_dict(active_es_id, pv_installation, recursive=True) # Adapt the potential (substract the installed value) pot.value = pot.value * (100 - percentage) / 100 # Emit the information to the front-end asset_list = [] port_list = [{ 'name': pv_outport.name, 'id': pv_outport.id, 'type': type(pv_outport).__name__, 'conn_to': [] }] capability_type = ESDLAsset.get_asset_capability_type( pv_installation) asset_list.append([ 'point', 'asset', pv_installation.name, pv_installation.id, type(pv_installation).__name__, [pv_geometry.lat, pv_geometry.lon], port_list, capability_type ]) emit( 'add_esdl_objects', { 'es_id': active_es_id, 'add_to_building': add_to_building, 'asset_pot_list': asset_list, 'zoom': False })
def process_area(esh, es_id, asset_list, building_list, area_bld_list, conn_list, area, level): area_bld_list.append(['Area', area.id, area.name, level]) # process subareas for ar in area.area: process_area(esh, es_id, asset_list, building_list, area_bld_list, conn_list, ar, level+1) # process assets in area for asset in area.asset: if isinstance(asset, esdl.AbstractBuilding): process_building(esh, es_id, asset_list, building_list, area_bld_list, conn_list, asset, False, level+1) if isinstance(asset, esdl.EnergyAsset): port_list = [] ports = asset.port for p in ports: p_asset = get_asset_and_coord_from_port_id(esh, es_id, p.id) p_asset_coord = p_asset['coord'] # get proper coordinate if asset is line conn_to_ids = [cp.id for cp in p.connectedTo] profile = p.profile profile_info_list = [] p_carr_id = None if p.carrier: p_carr_id = p.carrier.id if profile: profile_info_list = generate_profile_info(profile) port_list.append({'name': p.name, 'id': p.id, 'type': type(p).__name__, 'conn_to': conn_to_ids, 'profile': profile_info_list, 'carrier': p_carr_id}) if conn_to_ids: for pc in p.connectedTo: pc_asset = get_asset_and_coord_from_port_id(esh, es_id, pc.id) if pc_asset['asset'].containingBuilding: bld_pc_asset = pc_asset['asset'].containingBuilding if bld_pc_asset.geometry: if isinstance(bld_pc_asset.geometry, esdl.Point): pc_asset_coord = (bld_pc_asset.geometry.lat, bld_pc_asset.geometry.lon) elif isinstance(bld_pc_asset.geometry, esdl.Polygon): pc_asset_coord = ESDLGeometry.calculate_polygon_center(bld_pc_asset.geometry) else: pc_asset_coord = pc_asset['coord'] pc_carr_id = None if pc.carrier: pc_carr_id = pc.carrier.id conn_list.append({'from-port-id': p.id, 'from-port-carrier': p_carr_id, 'from-asset-id': p_asset['asset'].id, 'from-asset-coord': p_asset_coord, 'to-port-id': pc.id, 'to-port-carrier': pc_carr_id, 'to-asset-id': pc_asset['asset'].id, 'to-asset-coord': pc_asset_coord}) geom = asset.geometry if geom: if isinstance(geom, esdl.Point): lat = geom.lat lon = geom.lon capability_type = ESDLAsset.get_asset_capability_type(asset) asset_list.append(['point', 'asset', asset.name, asset.id, type(asset).__name__, [lat, lon], port_list, capability_type]) if isinstance(geom, esdl.Line): coords = [] for point in geom.point: coords.append([point.lat, point.lon]) asset_list.append(['line', 'asset', asset.name, asset.id, type(asset).__name__, coords, port_list]) if isinstance(geom, esdl.Polygon): # if isinstance(asset, esdl.WindParc) or isinstance(asset, esdl.PVParc) or isinstance(asset, esdl.WindPark) or isinstance(asset, esdl.PVPark): coords = ESDLGeometry.parse_esdl_subpolygon(geom.exterior, False) # [lon, lat] coords = ESDLGeometry.exchange_coordinates(coords) # --> [lat, lon] capability_type = ESDLAsset.get_asset_capability_type(asset) # print(coords) asset_list.append(['polygon', 'asset', asset.name, asset.id, type(asset).__name__, coords, port_list, capability_type]) for potential in area.potential: geom = potential.geometry if geom: if isinstance(geom, esdl.Point): lat = geom.lat lon = geom.lon asset_list.append( ['point', 'potential', potential.name, potential.id, type(potential).__name__, [lat, lon]]) if isinstance(geom, esdl.Polygon): coords = [] for point in geom.exterior.point: coords.append([point.lat, point.lon]) asset_list.append(['polygon', 'potential', potential.name, potential.id, type(potential).__name__, coords])
def process_building(esh, es_id, asset_list, building_list, area_bld_list, conn_list, building, bld_editor, level): # Add building to list that is shown in a dropdown at the top area_bld_list.append(['Building', building.id, building.name, level]) # Determine if building has assets building_has_assets = False if building.asset: for basset in building.asset: if isinstance(basset, esdl.EnergyAsset): building_has_assets = True break # Generate information for drawing building (as a point or a polygon) if isinstance(building, esdl.Building) or isinstance(building, esdl.AggregatedBuilding): geometry = building.geometry bld_KPIs = create_building_KPIs(building) if geometry: if isinstance(geometry, esdl.Point): building_list.append( ['point', building.name, building.id, type(building).__name__, [geometry.lat, geometry.lon], building_has_assets, bld_KPIs]) bld_coord = (geometry.lat, geometry.lon) elif isinstance(geometry, esdl.Polygon): coords = ESDLGeometry.parse_esdl_subpolygon(building.geometry.exterior, False) # [lon, lat] coords = ESDLGeometry.exchange_coordinates(coords) # --> [lat, lon] # building_list.append(['polygon', building.name, building.id, type(building).__name__, coords, building_has_assets]) boundary = ESDLGeometry.create_boundary_from_geometry(geometry) building_list.append(['polygon', building.name, building.id, type(building).__name__, boundary['coordinates'], building_has_assets, bld_KPIs]) # bld_coord = coords bld_coord = ESDLGeometry.calculate_polygon_center(geometry) elif building.containingBuilding: # BuildingUnit bld_geom = building.containingBuilding.geometry if bld_geom: if isinstance(bld_geom, esdl.Point): bld_coord = (bld_geom.lat, bld_geom.lon) elif isinstance(bld_geom, esdl.Polygon): bld_coord = ESDLGeometry.calculate_polygon_center(bld_geom) # Iterate over all assets in building to gather all required information for basset in building.asset: if isinstance(basset, esdl.AbstractBuilding): process_building(esh, es_id, asset_list, building_list, area_bld_list, conn_list, basset, bld_editor, level + 1) else: # Create a list of ports for this asset port_list = [] ports = basset.port for p in ports: conn_to = p.connectedTo conn_to_id_list = [ct.id for ct in conn_to] # TODO: add profile_info and carrier port_list.append({'name': p.name, 'id': p.id, 'type': type(p).__name__, 'conn_to': conn_to_id_list}) geom = basset.geometry coord = () if geom: # Individual asset in Building has its own geometry information if isinstance(geom, esdl.Point): lat = geom.lat lon = geom.lon coord = (lat, lon) capability_type = ESDLAsset.get_asset_capability_type(basset) if bld_editor: asset_list.append(['point', 'asset', basset.name, basset.id, type(basset).__name__, [lat, lon], port_list, capability_type]) else: send_alert("Assets within buildings with geometry other than esdl.Point are not supported") # Inherit geometry from containing building # if level > 0: # coord = bld_coord ports = basset.port for p in ports: p_carr_id = None if p.carrier: p_carr_id = p.carrier.id conn_to = p.connectedTo if conn_to: for pc in conn_to: in_different_buildings = False pc_asset = get_asset_and_coord_from_port_id(esh, es_id, pc.id) # If the asset the current asset connects to, is in a building... if pc_asset['asset'].containingBuilding: bld_pc_asset = pc_asset['asset'].containingBuilding bld_basset = basset.containingBuilding # If the asset is in a different building ... if not bld_pc_asset == bld_basset: in_different_buildings = True if bld_pc_asset.geometry: if bld_editor: # ... connect to the left border pc_asset_coord = (coord[0], 0) else: # ... use the building coordinate instead of the asset coordinate if isinstance(bld_pc_asset.geometry, esdl.Point): pc_asset_coord = (bld_pc_asset.geometry.lat, bld_pc_asset.geometry.lon) elif isinstance(bld_pc_asset.geometry, esdl.Polygon): pc_asset_coord = ESDLGeometry.calculate_polygon_center(bld_pc_asset.geometry) # If connecting to a building outside of the current, replace current asset # coordinates with building coordinates too if not bld_editor: coord = bld_coord else: # asset is in the same building, use asset's own coordinates pc_asset_coord = pc_asset['coord'] else: # other asset is not in a building if bld_editor: # ... connect to the left border pc_asset_coord = (coord[0], 0) else: # ... just use asset's location pc_asset_coord = pc_asset['coord'] pc_carr_id = None if pc.carrier: pc_carr_id = pc.carrier.id # Add connections if we're editing a building or if the connection is between two different buildings # ( The case of an asset in an area that is connected with an asset in a building is handled # in process_area (now all connections are added twice, from both sides) ) if bld_editor or in_different_buildings: conn_list.append({'from-port-id': p.id, 'from-port-carrier': p_carr_id, 'from-asset-id': basset.id, 'from-asset-coord': coord, 'to-port-id': pc.id, 'to-port-carrier': pc_carr_id, 'to-asset-id': pc_asset['asset'].id, 'to-asset-coord': pc_asset_coord}) if bld_editor: for potential in building.potential: geom = potential.geometry if geom: if isinstance(geom, esdl.Point): lat = geom.lat lon = geom.lon asset_list.append( ['point', 'potential', potential.name, potential.id, type(potential).__name__, [lat, lon]])
def call_esdl_service(self, service_params): """Actually call an ESDL service.""" esh = get_handler() active_es_id = get_session("active_es_id") # {'service_id': '18d106cf-2af1-407d-8697-0dae23a0ac3e', 'area_scope': 'provincies', 'area_id': '12', # 'query_parameters': {'bebouwingsafstand': '32432', 'restrictie': 'vliegveld', 'preferentie': 'infrastructuur', 'geometrie': 'true'}} # Find the currently active service. service = None for config_service in self.config: if config_service["id"] == service_params["service_id"]: service = config_service break # If it's a workflow, lookin its steps. if config_service["type"] == "workflow": for step in config_service["workflow"]: if (step["type"] == "service" and step["service"]["id"] == service_params["service_id"]): service = step["service"] break if service is None: return False, None url = service["url"] headers = service["headers"] if service.get("with_jwt_token", False): jwt_token = get_session("jwt-token") headers["Authorization"] = f"Bearer {jwt_token}" body = {} if "send_email_in_post_body_parameter" in service: body[service["send_email_in_post_body_parameter"]] = get_session( "user-email") if service["type"] == "geo_query": area_scope_tag = service["geographical_scope"]["url_area_scope"] area_id_tag = service["geographical_scope"]["url_area_id"] area_scope = service_params["area_scope"] url = url.replace(area_scope_tag, area_scope) ares_id = service_params["area_id"] url = url.replace(area_id_tag, ares_id) if "url_area_subscope" in service["geographical_scope"]: area_subscope_tag = service["geographical_scope"][ "url_area_subscope"] area_subscope = service_params["area_subscope"] url = url.replace(area_subscope_tag, area_subscope) elif service["type"] == "send_esdl": esdlstr = esh.to_string(active_es_id) if service["body"] == "url_encoded": body["energysystem"] = urllib.parse.quote(esdlstr) # print(body) elif service["body"] == "base64_encoded": esdlstr_bytes = esdlstr.encode('ascii') esdlstr_base64_bytes = base64.b64encode(esdlstr_bytes) body["energysystem"] = esdlstr_base64_bytes.decode('ascii') else: body = esdlstr elif service["type"] == "simulation": esdlstr = esh.to_string(active_es_id) if service["body"] == "url_encoded": body["energysystem"] = urllib.parse.quote(esdlstr) elif service["body"] == "base64_encoded": esdlstr_bytes = esdlstr.encode('ascii') esdlstr_base64_bytes = base64.b64encode(esdlstr_bytes) body["energysystem"] = esdlstr_base64_bytes.decode('ascii') else: body = esdlstr query_params = service_params["query_parameters"] config_service_params = service["query_parameters"] if query_params: first_qp = True for key in query_params: if query_params[ key]: # to filter empty lists for multi-selection parameters for cfg_service_param in config_service_params: if cfg_service_param["parameter_name"] == key: if "location" in cfg_service_param: if cfg_service_param["location"] == "url": url = url.replace( "<" + cfg_service_param["parameter_name"] + ">", query_params[key], ) elif cfg_service_param[ "location"] == "body" and isinstance( body, dict): body[cfg_service_param[ "parameter_name"]] = query_params[key] else: if first_qp: url = url + "?" else: url = url + "&" url = (url + key + "=" + self.array2list(query_params[key])) first_qp = False try: if service["http_method"] == "get": r = requests.get(url, headers=headers) elif service["http_method"] == "post": if service["type"] == "json": kwargs = {"json": body} else: kwargs = {"data": body} r = requests.post(url, headers=headers, **kwargs) else: # Should not happen, there should always be a method. return False, None if (service["http_method"] == "get" and r.status_code == 200) or \ (service["http_method"] == "post" and r.status_code == 201): # print(r.text) if service["result"][0]["action"] == "esdl": esh.add_from_string(service["name"], r.text) return True, None elif service["result"][0]["action"] == "print": return True, json.loads(r.text) elif service["result"][0]["action"] == "add_assets": es_edit = esh.get_energy_system(es_id=active_es_id) instance = es_edit.instance area = instance[0].area asset_str_list = json.loads(r.text) try: for asset_str in asset_str_list["add_assets"]: asset = ESDLAsset.load_asset_from_string(asset_str) esh.add_object_to_dict(active_es_id, asset) ESDLAsset.add_asset_to_area( es_edit, asset, area.id) asset_ui, conn_list = energy_asset_to_ui( esh, active_es_id, asset) emit( "add_esdl_objects", { "es_id": active_es_id, "asset_pot_list": [asset_ui], "zoom": True, }, ) emit( "add_connections", { "es_id": active_es_id, "conn_list": conn_list }, ) except Exception as e: logger.warning("Exception occurred: " + str(e)) return False, None return True, {"send_message_to_UI_but_do_nothing": {}} elif service["result"][0]["action"] == "show_message": return True, {"message": service["result"][0]["message"]} else: logger.warning("Error running ESDL service - response " + str(r.status_code) + " with reason: " + str(r.reason)) logger.warning(r) logger.warning(r.content) return False, None except Exception as e: logger.warning("Error accessing external ESDL service: " + str(e)) return False, None return False, None
def call_esdl_service(self, service_params): """Actually call an ESDL service.""" esh = get_handler() active_es_id = get_session("active_es_id") # {'service_id': '18d106cf-2af1-407d-8697-0dae23a0ac3e', 'area_scope': 'provincies', 'area_id': '12', # 'query_parameters': {'bebouwingsafstand': '32432', 'restrictie': 'vliegveld', 'preferentie': 'infrastructuur', 'geometrie': 'true'}} # Find the currently active service. service = None # services_list = get_session('services_list') user_email = get_session('user-email') role = get_session('user-role') services_list = self.get_user_services_list(user_email, role) for config_service in services_list: if config_service["id"] == service_params["service_id"]: service = config_service break # If it's a workflow, look in its steps. if config_service["type"] in ("workflow", "vueworkflow"): for step in config_service["workflow"]: if (step["type"] in ("service", "custom")): if "service" in step and step["service"][ "id"] == service_params["service_id"]: service = step["service"] break if service is None: return False, None url = service["url"] headers = service["headers"] if service.get("with_jwt_token", False): jwt_token = get_session("jwt-token") headers["Authorization"] = f"Bearer {jwt_token}" body = {} if "send_email_in_post_body_parameter" in service: body[service["send_email_in_post_body_parameter"]] = get_session( "user-email") if service["type"] == "geo_query": area_scope_tag = service["geographical_scope"]["url_area_scope"] area_id_tag = service["geographical_scope"]["url_area_id"] area_scope = service_params["area_scope"] url = url.replace(area_scope_tag, area_scope) ares_id = service_params["area_id"] url = url.replace(area_id_tag, ares_id) if "url_area_subscope" in service["geographical_scope"]: area_subscope_tag = service["geographical_scope"][ "url_area_subscope"] area_subscope = service_params["area_subscope"] url = url.replace(area_subscope_tag, area_subscope) elif service["type"].startswith("send_esdl"): esdlstr = esh.to_string(active_es_id) if service["body"] == "url_encoded": body["energysystem"] = urllib.parse.quote(esdlstr) # print(body) elif service["body"] == "base64_encoded": esdlstr_bytes = esdlstr.encode('utf-8') esdlstr_base64_bytes = base64.b64encode(esdlstr_bytes) body["energysystem"] = esdlstr_base64_bytes.decode('utf-8') else: body = esdlstr elif service["type"] == "simulation": esdlstr = esh.to_string(active_es_id) if service["body"] == "url_encoded": body["energysystem"] = urllib.parse.quote(esdlstr) elif service["body"] == "base64_encoded": esdlstr_bytes = esdlstr.encode('utf-8') esdlstr_base64_bytes = base64.b64encode(esdlstr_bytes) body["energysystem"] = esdlstr_base64_bytes.decode('utf-8') else: body = esdlstr if "body_config" in service: if service["body_config"]["type"] == "text": esdlstr = esh.to_string(active_es_id) if service["body_config"]["encoding"] == "none": body = esdlstr if service["body_config"]["encoding"] == "url_encoded": body = urllib.parse.quote(esdlstr) if service["body_config"]["encoding"] == "base64_encoded": esdlstr_bytes = esdlstr.encode('utf-8') esdlstr_base64_bytes = base64.b64encode(esdlstr_bytes) body = esdlstr_base64_bytes.decode('utf-8') if service["body_config"]["type"] == "json": body = {} for param in service["body_config"]['parameters']: if param["type"] == "esdl": esdlstr = esh.to_string(active_es_id) if param["encoding"] == "none": body[param["parameter"]] = esdlstr if param["encoding"] == "url_encoded": body[param["parameter"]] = urllib.parse.quote( esdlstr) if param["encoding"] == "base64_encoded": esdlstr_bytes = esdlstr.encode('utf-8') esdlstr_base64_bytes = base64.b64encode( esdlstr_bytes) body[param[ "parameter"]] = esdlstr_base64_bytes.decode( 'utf-8') if param["type"] == "value": body[param["parameter"]] = param["value"] if param["type"] == "json_string": body_params = service_params["body_config"] for bp in body_params: if param["parameter"] == bp: body[param["parameter"]] = body_params[bp] query_params = service_params["query_parameters"] config_service_params = service.get("query_parameters", {}) if query_params: first_qp = True for key in query_params: if query_params[ key]: # to filter empty lists for multi-selection parameters for cfg_service_param in config_service_params: if cfg_service_param["parameter_name"] == key: if "location" in cfg_service_param: if cfg_service_param["location"] == "url": url = url.replace( "<" + cfg_service_param["parameter_name"] + ">", str(query_params[key]), ) elif cfg_service_param[ "location"] == "body" and isinstance( body, dict): body[cfg_service_param[ "parameter_name"]] = query_params[key] else: if first_qp: url = url + "?" else: url = url + "&" url = (url + key + "=" + self.array2list(query_params[key])) first_qp = False try: if service["http_method"] == "get": r = requests.get(url, headers=headers) elif service["http_method"] == "post": if service["type"].endswith("json") or ( "body_config" in service and service["body_config"]["type"] == "json"): kwargs = {"json": body} else: kwargs = {"data": body} r = requests.post(url, headers=headers, **kwargs) else: # Should not happen, there should always be a method. return False, None if r.status_code == 200 or r.status_code == 201: # print(r.text) if service["result"][0]["action"] == "esdl": if "encoding" in service["result"][0]: if service["result"][0]["encoding"] == "url_encoded": esdl_response = urllib.parse.quote(r.text) elif service["result"][0][ "encoding"] == "base64_encoded": esdlstr_bytes = r.text.encode('utf-8') esdlstr_base64_bytes = base64.b64decode( esdlstr_bytes) esdl_response = esdlstr_base64_bytes.decode( 'utf-8') else: esdl_response = r.text else: esdl_response = r.text es, parse_info = esh.add_from_string( service["name"], esdl_response) # TODO deal with parse_info? return True, None elif service["result"][0]["action"] == "print": return True, json.loads(r.text) elif service["result"][0]["action"] == "add_assets": es_edit = esh.get_energy_system(es_id=active_es_id) instance = es_edit.instance area = instance[0].area asset_str_list = json.loads(r.text) # Fix for services that return an ESDL string that represents one asset if isinstance(asset_str_list, str): asset_str_list = {"add_assets": [asset_str_list]} try: for asset_str in asset_str_list["add_assets"]: asset = ESDLAsset.load_asset_from_string(asset_str) esh.add_object_to_dict(active_es_id, asset) ESDLAsset.add_object_to_area( es_edit, asset, area.id) asset_ui, conn_list = energy_asset_to_ui( esh, active_es_id, asset) emit( "add_esdl_objects", { "es_id": active_es_id, "asset_pot_list": [asset_ui], "zoom": True, }, ) emit( "add_connections", { "es_id": active_es_id, "conn_list": conn_list }, ) except Exception as e: logger.warning("Exception occurred: " + str(e)) return False, None return True, {"send_message_to_UI_but_do_nothing": {}} elif service["result"][0]["action"] == "add_notes": es_edit = esh.get_energy_system(es_id=active_es_id) esi = es_edit.energySystemInformation if not esi: esi = es_edit.energySystemInformation = esdl.EnergySystemInformation( id=str(uuid.uuid4())) esh.add_object_to_dict(active_es_id, esi) notes = esi.notes if not notes: notes = esi.notes = esdl.Notes(id=str(uuid.uuid4())) esh.add_object_to_dict(active_es_id, notes) notes_from_service = ESDLAsset.load_asset_from_string( esdl_string=r.text) if isinstance(notes_from_service, esdl.Notes): notes_list = [] for note in list(notes_from_service.note): notes.note.append(note) esh.add_object_to_dict(active_es_id, note) map_location = note.mapLocation if map_location: coords = { 'lng': map_location.lon, 'lat': map_location.lat } notes_list.append({ 'id': note.id, 'location': coords, 'title': note.title, 'text': note.text, 'author': note.author }) # , 'date': n.date}) emit('add_notes', { 'es_id': active_es_id, 'notes_list': notes_list }) else: logger.error("Service with id " + service_params["service_id"] + " did not return a esdl.Notes object") return False, None return True, {"send_message_to_UI_but_do_nothing": {}} elif service["result"][0]["action"] == "asset_feedback": service_results = json.loads(r.text) asset_results_dict = dict() for sr in service_results: asset_results_dict[sr['assetID']] = sr['messages'] return True, {"asset_feedback": asset_results_dict} elif service["result"][0]["action"] == "show_message": return True, {"message": service["result"][0]["message"]} else: logger.warning("Error running ESDL service - response " + str(r.status_code) + " with reason: " + str(r.reason)) logger.warning(r) logger.warning(r.content) return False, str(r.content) except Exception as e: logger.exception("Error accessing external ESDL service: " + str(e)) return False, None return False, None