2023-01-10 12:12:01 -05:00
|
|
|
"""
|
|
|
|
City info
|
|
|
|
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
|
|
|
Copyright © 2022 Project Author name guillermo.gutierrezmorote@concordia.ca
|
|
|
|
"""
|
|
|
|
import json
|
2023-01-13 12:01:13 -05:00
|
|
|
from flask_apispec import use_kwargs, doc
|
2023-01-16 15:31:02 -05:00
|
|
|
from flask import Response, request, g
|
2023-01-10 12:12:01 -05:00
|
|
|
from flask_restful import Resource
|
|
|
|
from hub_api.helpers.session_helper import refresh_session
|
2023-01-13 12:01:13 -05:00
|
|
|
from marshmallow import fields, Schema
|
|
|
|
from hub_api.helpers.auth import role_required
|
|
|
|
from persistence.models import UserRoles
|
|
|
|
from hub_logger import logger
|
2023-01-16 15:31:02 -05:00
|
|
|
from flasgger import swag_from
|
|
|
|
from imports.geometry_factory import GeometryFactory
|
|
|
|
from pathlib import Path
|
|
|
|
from imports.db_factory import DBFactory
|
|
|
|
import os
|
2023-01-13 12:01:13 -05:00
|
|
|
|
|
|
|
|
|
|
|
class AuthorizationHeader(Schema):
|
|
|
|
Authorization = fields.Str(required=True, description='Authorization token')
|
|
|
|
AppID = fields.Str(required=True, description='ID of app accessing API')
|
|
|
|
|
|
|
|
|
|
|
|
class CitySchema(Schema):
|
|
|
|
city_file = fields.Raw(type='file', required=True, description='City file')
|
2023-01-10 12:12:01 -05:00
|
|
|
|
|
|
|
|
|
|
|
class CityInfo(Resource):
|
|
|
|
def __init__(self):
|
|
|
|
pass
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
def get():
|
|
|
|
session = refresh_session(request)
|
|
|
|
if session is None:
|
|
|
|
return Response(json.dumps({'error': 'invalid session'}), status=401)
|
|
|
|
headers = session.headers
|
|
|
|
|
|
|
|
city = session.city
|
|
|
|
# TODO: this is only for dompark project and need to be removed in future versions.
|
|
|
|
floor_area = 0
|
|
|
|
wall_construction = 'unknown'
|
|
|
|
floor_construction = 'unknown'
|
|
|
|
roof_construction = 'unknown'
|
|
|
|
window_type = 'unknown'
|
|
|
|
building_dic = {}
|
|
|
|
for building in city.buildings:
|
|
|
|
|
|
|
|
usages = [] # This is only valid for dompark project as all the building have the same usage
|
|
|
|
if building.lower_corner[2] == 0:
|
|
|
|
floor_area += building.floor_area
|
|
|
|
for internal_zone in building.internal_zones:
|
|
|
|
for usage_zone in internal_zone.usage_zones:
|
|
|
|
usages.append({'percentage': usage_zone.percentage, 'usage': usage_zone.usage})
|
|
|
|
for thermal_zone in internal_zone.thermal_zones:
|
|
|
|
for thermal_boundary in thermal_zone.thermal_boundaries:
|
|
|
|
if thermal_boundary.parent_surface.type == 'Ground':
|
|
|
|
floor_construction = thermal_boundary.construction_name
|
|
|
|
elif thermal_boundary.parent_surface.type == 'Wall':
|
|
|
|
wall_construction = thermal_boundary.construction_name
|
|
|
|
for thermal_opening in thermal_boundary.thermal_openings:
|
|
|
|
if thermal_opening.construction_name is not None:
|
|
|
|
window_type = thermal_opening.construction_name
|
|
|
|
break
|
|
|
|
else:
|
|
|
|
roof_construction = thermal_boundary.construction_name
|
|
|
|
name = building.human_readable_name
|
|
|
|
year_of_construction = str(building.year_of_construction)
|
|
|
|
building_dic = {
|
|
|
|
'name': str(name),
|
|
|
|
'floor_area': str(floor_area),
|
|
|
|
'year_of_construction': str(year_of_construction),
|
|
|
|
'usages': usages,
|
|
|
|
'wall_construction': wall_construction,
|
|
|
|
'floor_construction': floor_construction,
|
|
|
|
'roof_construction': roof_construction,
|
|
|
|
'window_type': window_type,
|
|
|
|
'default_archetype': 'industry ASHRAE_2004:4A non_standard_dompark'
|
|
|
|
}
|
|
|
|
|
|
|
|
buildings = [building_dic]
|
|
|
|
response = {'city_name': 'Montreal',
|
|
|
|
'climate_reference_city': str(city.climate_reference_city),
|
|
|
|
'buildings': buildings
|
|
|
|
}
|
|
|
|
return Response(json.dumps(response), headers=headers)
|
2023-01-13 12:01:13 -05:00
|
|
|
|
|
|
|
|
2023-01-16 15:31:02 -05:00
|
|
|
class City(Resource):
|
|
|
|
|
|
|
|
def __init__(self):
|
|
|
|
pass
|
|
|
|
|
|
|
|
#@role_required([UserRoles.Admin.value])
|
|
|
|
@swag_from("docs/openapi-specs.yml", methods=['POST'])
|
|
|
|
def post(self):
|
|
|
|
allowed_ext = {'gml', '3dm', 'xml', 'obj', 'rhino'}
|
2023-01-13 12:01:13 -05:00
|
|
|
try:
|
2023-01-16 15:31:02 -05:00
|
|
|
city_file = request.files['city_file']
|
|
|
|
ext = city_file.filename.rsplit('.', 1)[1].lower()
|
|
|
|
|
|
|
|
if ext in allowed_ext:
|
|
|
|
city_file_type = ext
|
|
|
|
if ext == 'gml':
|
|
|
|
city_file_type = 'citygml'
|
|
|
|
elif ext == '3dm':
|
|
|
|
city_file_type = 'rhino'
|
|
|
|
|
|
|
|
file_path = (Path(__file__).parent.parent / 'data/uploaded_city/{}'.format(city_file.filename)).resolve()
|
|
|
|
city_file.save(file_path)
|
|
|
|
city = GeometryFactory(city_file_type, file_path).city
|
|
|
|
db_factory = DBFactory(city=city, db_name='hub_prod', app_env='PROD',
|
|
|
|
dotenv_path="{}/.env".format(os.path.expanduser('~')))
|
|
|
|
saved_city = db_factory.persist_city(1)
|
|
|
|
if os.path.exists(file_path):
|
|
|
|
os.remove(file_path)
|
|
|
|
if type(saved_city) is not dict:
|
|
|
|
return Response(response=json.dumps({
|
|
|
|
'id': saved_city.id, 'name': saved_city.name, 'srs_name': saved_city.srs_name,
|
|
|
|
'time_zone': saved_city.time_zone, 'version': saved_city.city_version, 'country': saved_city.country_code,
|
|
|
|
'lat': saved_city.latitude, 'lon': saved_city.longitude, 'lower_corner': saved_city.lower_corner,
|
|
|
|
'upper_corner': saved_city.upper_corner, 'created': saved_city.created, 'updated': saved_city.updated,
|
|
|
|
'user': {'id': saved_city.user.id, 'name': saved_city.user.name, 'email': saved_city.user.email,
|
|
|
|
'role': saved_city.user.role.value}
|
|
|
|
}, default=str), status=201)
|
|
|
|
return Response(response=json.dumps(saved_city), status=200)
|
|
|
|
else:
|
|
|
|
return Response(response=json.dumps({'err_msg': 'Unknown city file type'}), status=400)
|
2023-01-13 12:01:13 -05:00
|
|
|
except Exception as err:
|
|
|
|
logger.error(err)
|
2023-01-16 15:31:02 -05:00
|
|
|
return Response(response=json.dumps({'err_msg': 'Sorry an error occurred while creating city'}), status=400)
|