diff --git a/hub/city_model_structure/energy_systems/heat_pump.py b/hub/city_model_structure/energy_systems/heat_pump.py index bb78dc72..120155c5 100644 --- a/hub/city_model_structure/energy_systems/heat_pump.py +++ b/hub/city_model_structure/energy_systems/heat_pump.py @@ -4,6 +4,8 @@ SPDX - License - Identifier: LGPL - 3.0 - or -later Copyright © 2022 Concordia CERC group Project Coder Peter Yefi peteryefi@gmail.com """ +from typing import List +from pandas.core.series import Series class HeatPump: @@ -13,6 +15,8 @@ class HeatPump: def __init__(self): self._model = None + self._hp_monthly_fossil_consumption = None + self._hp_monthly_electricity_demand = None @property def model(self) -> str: @@ -30,3 +34,31 @@ class HeatPump: """ if self._model is None: self._model = value + + @property + def hp_monthly_fossil_consumption(self) -> List: + """ + Fossil fuel consumption that results from insel simulation + ":return: [] + :return: + """ + return self._hp_monthly_fossil_consumption + + @hp_monthly_fossil_consumption.setter + def hp_monthly_fossil_consumption(self, value): + if type(value) is Series: + self._hp_monthly_fossil_consumption = value + + @property + def hp_monthly_electricity_demand(self) -> List: + """ + Electricity demand that results from insel simulation + ":return: [] + :return: + """ + return self._hp_monthly_electricity_demand + + @hp_monthly_electricity_demand.setter + def hp_monthly_electricity_demand(self, value): + if type(value) == Series: + self._hp_monthly_electricity_demand = value diff --git a/hub/city_model_structure/iot/sensor_measure.py b/hub/city_model_structure/iot/sensor_measure.py index 7c2d2223..12ab5811 100644 --- a/hub/city_model_structure/iot/sensor_measure.py +++ b/hub/city_model_structure/iot/sensor_measure.py @@ -5,6 +5,7 @@ Copyright © 2022 Concordia CERC group Project Coder Guille Gutierrez guillermo.gutierrezmorote@concordia.ca """ + class SensorMeasure: def __init__(self, latitude, longitude, utc_timestamp, value): self._latitude = latitude diff --git a/hub/city_model_structure/iot/sensor_type.py b/hub/city_model_structure/iot/sensor_type.py index 49596c50..a9477779 100644 --- a/hub/city_model_structure/iot/sensor_type.py +++ b/hub/city_model_structure/iot/sensor_type.py @@ -7,6 +7,7 @@ Project Coder Guille Gutierrez guillermo.gutierrezmorote@concordia.ca from enum import Enum + class SensorType(Enum): HUMIDITY = 0 TEMPERATURE = 1 diff --git a/hub/exports/db_factory.py b/hub/exports/db_factory.py index 32906fde..c4c7cf7f 100644 --- a/hub/exports/db_factory.py +++ b/hub/exports/db_factory.py @@ -46,7 +46,10 @@ class DBFactory: return self._application.get_by_uuid(application_uuid) def user_info(self, name, password, application_id): - return self._user.get_by_name_application_and_password(name, password, application_id) + return self._user.get_by_name_application_id_and_password(name, password, application_id) + + def user_login(self, name, password, application_uuid): + return self._user.get_by_name_application_uuid_and_password(name, password, application_uuid) def building_info(self, name, city_id): return self._city_object.get_by_name_and_city(name, city_id) diff --git a/hub/exports/user_factory.py b/hub/exports/user_factory.py index 0c932418..68a3324d 100644 --- a/hub/exports/user_factory.py +++ b/hub/exports/user_factory.py @@ -4,8 +4,7 @@ SPDX - License - Identifier: LGPL - 3.0 - or -later Copyright © 2022 Concordia CERC group Project CoderPeter Yefi peteryefi@gmail.com """ -from hub.persistence import UserRepo - +from hub.persistence import User class UserFactory: """ @@ -13,7 +12,7 @@ class UserFactory: """ def __init__(self, db_name, app_env, dotenv_path): - self._user_repo = UserRepo(db_name=db_name, app_env=app_env, dotenv_path=dotenv_path) + self._user_repo = User(db_name=db_name, app_env=app_env, dotenv_path=dotenv_path) def login_user(self, email: str, password: str): """ diff --git a/hub/helpers/data/montreal_function_to_hub_function.py b/hub/helpers/data/montreal_function_to_hub_function.py index 1f8e88ce..5b107196 100644 --- a/hub/helpers/data/montreal_function_to_hub_function.py +++ b/hub/helpers/data/montreal_function_to_hub_function.py @@ -10,11 +10,10 @@ import hub.helpers.constants as cte class MontrealFunctionToHubFunction: - # Todo: "office" "Mausolée" and "hotel/motel" need to be replaced for a constant value. def __init__(self): self._dictionary = { - "Administration publique municipale et régionale": "Office", - "Administration publique provinciale": "Office", + "Administration publique municipale et régionale": cte.MEDIUM_OFFICE, + "Administration publique provinciale": cte.MEDIUM_OFFICE, "Agence de voyages ou d'expéditions": cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD, "Aiguillage et cour de triage de chemins de fer": cte.WAREHOUSE, "Amphithéâtre et auditorium": cte.EVENT_LOCATION, @@ -52,7 +51,7 @@ class MontrealFunctionToHubFunction: "Autres bases et réserves militaires": cte.WAREHOUSE, "Autres centres de recherche": cte.SECONDARY_SCHOOL, "Autres centres de services sociaux ou bureaux de travailleurs sociaux": cte.OFFICE_AND_ADMINISTRATION, - "Autres centres et réseaux de télévision et de radiodiffusion (système combiné)": "Office", + "Autres centres et réseaux de télévision et de radiodiffusion (système combiné)": cte.MEDIUM_OFFICE, "Autres entreposages": cte.WAREHOUSE, "Autres espaces de plancher inoccupé": cte.WAREHOUSE, "Autres espaces de terrain et étendues d'eau inexploités": cte.WAREHOUSE, @@ -99,11 +98,11 @@ class MontrealFunctionToHubFunction: "Autres maisons et locaux fraternels": cte.OFFICE_AND_ADMINISTRATION, "Autres maisons pour personnes retraitées": cte.OFFICE_AND_ADMINISTRATION, "Autres parcs": cte.WAREHOUSE, - "Autres routes et voies publiques": "Office", - "Autres résidences d'étudiants": "Office", - "Autres résidences provisoires": "Office", + "Autres routes et voies publiques": cte.WAREHOUSE, + "Autres résidences d'étudiants": cte.DORMITORY, + "Autres résidences provisoires": cte.DORMITORY, "Autres services connexes aux valeurs mobilières et aux marchandises": cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD, - "Autres services d'affaires": "Office", + "Autres services d'affaires": cte.MEDIUM_OFFICE, "Autres services d'aqueduc et d'irrigation": cte.WAREHOUSE, "Autres services de construction de bâtiments": cte.WAREHOUSE, "Autres services de génie civil (entrepreneur général)": cte.WAREHOUSE, @@ -149,7 +148,7 @@ class MontrealFunctionToHubFunction: "Centre commercial super régional (200 magasins et plus)": cte.STRIP_MALL, "Centre communautaire ou de quartier (inclus Centre diocésain)": cte.OFFICE_AND_ADMINISTRATION, "Centre d'accueil ou établissement curatif (inclus centre de réadaptation pour handicapés physiques et mentaux)": cte.OUT_PATIENT_HEALTH_CARE, - "Centre d'appels téléphoniques": "Office", + "Centre d'appels téléphoniques": cte.MEDIUM_OFFICE, "Centre d'entraide et de ressources communautaires (inclus ressources d'hébergement de meubles et d'alimentation)": cte.OUT_PATIENT_HEALTH_CARE, "Centre d'entreposage de produits pétroliers (pétrole brutgaz pétrole liquéfiémazout domestique et autres produits raffinés)": cte.WAREHOUSE, "Centre d'entreposage du gaz (avant distrib.aux consommateurs)": cte.WAREHOUSE, @@ -200,13 +199,13 @@ class MontrealFunctionToHubFunction: "Gare de chemins de fer": cte.WAREHOUSE, "Gymnase et formation athlétique": cte.SPORTS_LOCATION, "Hangar à avion": cte.WAREHOUSE, - "Hôtel (incluant les hôtels-motels)": "Hotel/Motel", - "Hôtel résidentiel": "Hotel/Motel", + "Hôtel (incluant les hôtels-motels)": cte.SMALL_HOTEL, + "Hôtel résidentiel": cte.SMALL_HOTEL, "Immeuble commercial": cte.STAND_ALONE_RETAIL, - "Immeuble non résidentiel en construction": "Office", + "Immeuble non résidentiel en construction": cte.NON_HEATED, "Immeuble résidentiel en construction": cte.RESIDENTIAL, - "Immeuble à bureaux": "Office", - "Immeuble à temps partagé («time share») Propriété ou copropriété ou groupe d'usufruitier ont chacun droit de jouissancepériodique et successif.": "Office", + "Immeuble à bureaux": cte.MEDIUM_OFFICE, + "Immeuble à temps partagé («time share») Propriété ou copropriété ou groupe d'usufruitier ont chacun droit de jouissancepériodique et successif.": cte.MEDIUM_OFFICE, "Incinérateur": cte.INDUSTRY, "Industrie d'accessoires vestimentaires et d'autres vêtements": cte.INDUSTRY, "Industrie d'alcools destinés à la consommation (distillerie)": cte.INDUSTRY, @@ -308,27 +307,27 @@ class MontrealFunctionToHubFunction: "Installation portuaire en général": cte.WAREHOUSE, "Jardin botanique": cte.WAREHOUSE, "Ligne de l'oléoduc": cte.WAREHOUSE, - "Local pour les associations fraternelles": "Office", + "Local pour les associations fraternelles": cte.EVENT_LOCATION, "Logement": cte.RESIDENTIAL, "Logement vacant dans un bâtiment comportant plusieurs logements ou autres locaux": cte.RESIDENTIAL, - "Loisir et autres activités culturelles": "Office", - "Maison d'agentsde courtiers et de services d'administration des biens-fonds": "Office", - "Maison d'étudiants (collège et université)": "Office", - "Maison de chambres et pension": "Office", - "Maison de chambres pour personnes ayant une déficience intellectuelle": "Office", - "Maison de courtiers et de négociants de marchandises": "Office", - "Maison de réhabilitation": "Office", - "Maison des jeunes": "Office", - "Maison pour personnes en difficulté (séjours périodes limitées)": "Office", + "Loisir et autres activités culturelles": cte.HALL, + "Maison d'agents de courtiers et de services d'administration des biens-fonds": cte.MEDIUM_OFFICE, + "Maison d'étudiants (collège et université)": cte.DORMITORY, + "Maison de chambres et pension": cte.DORMITORY, + "Maison de chambres pour personnes ayant une déficience intellectuelle": cte.DORMITORY, + "Maison de courtiers et de négociants de marchandises": cte.MEDIUM_OFFICE, + "Maison de réhabilitation": cte.HOSPITAL, + "Maison des jeunes": cte.HALL, + "Maison pour personnes en difficulté (séjours périodes limitées)": cte.HOSPITAL, "Maison pour personnes retraitées autonomes": cte.DORMITORY, "Maison pour personnes retraitées non autonomes (inclus les CHLSD)": cte.DORMITORY, "Marché public": cte.STRIP_MALL, - "Meunerie et minoterie": "Office", + "Meunerie et minoterie": cte.MEDIUM_OFFICE, "Monastère": cte.DORMITORY, "Monument et site historique": cte.EVENT_LOCATION, - "Motel": "hotel/Motel", + "Motel": cte.SMALL_HOTEL, "Musée": cte.EVENT_LOCATION, - "Organisme international et autres organismes extraterritoriaux": "Office", + "Organisme international et autres organismes extraterritoriaux": cte.MEDIUM_OFFICE, "Parc d'amusement (extérieur)": cte.NON_HEATED, "Parc de maisons mobiles (fonds de terre seulement)": cte.NON_HEATED, "Parc pour la récréation en général": cte.NON_HEATED, @@ -354,7 +353,7 @@ class MontrealFunctionToHubFunction: "Réparation et entretien des avions": cte.WAREHOUSE, "Réserve pour la protection de la faune": cte.NON_HEATED, "Réservoir d'eau (installation d'emmagasinage de l'eau par retenue et réservoirs)": cte.NON_HEATED, - "Résidence de tourismeappartement maison ou chalet (meublé et équipé pour repas)": "hotel/Motel", + "Résidence de tourismeappartement maison ou chalet (meublé et équipé pour repas)": cte.SMALL_HOTEL, "Salle d'exposition": cte.EVENT_LOCATION, "Salle et terrain de squash de racquetball et de tennis": cte.SPORTS_LOCATION, "Salle ou salon de quilles": cte.NON_HEATED, @@ -391,23 +390,23 @@ class MontrealFunctionToHubFunction: "Service de location de boites postales (sauf le publipostage) et centre de courrier privé": cte.OFFICE_AND_ADMINISTRATION, "Service de location de camions de remorques utilitaires et de véhicules de plaisance": cte.WAREHOUSE, "Service de maçonnerie (entrepreneur spécialisé)": cte.INDUSTRY, - "Service de messagers": "Office", - "Service de notaires": "Office", + "Service de messagers": cte.MEDIUM_OFFICE, + "Service de notaires": cte.MEDIUM_OFFICE, "Service de paysagement ou de déneigement": cte.WAREHOUSE, "Service de petite menuiserie et de finition (entrepreneur spécialisé)": cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD, "Service de plomberie de chauffagede climatisation et de ventilation (entrepreneur spécialisé)": cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD, "Service de police fédérale et activités connexes": cte.OFFICE_AND_ADMINISTRATION, "Service de police municipale et activités connexes": cte.OFFICE_AND_ADMINISTRATION, "Service de pose de portesde fenêtres et de panneaux de verre": cte.WAREHOUSE, - "Service de publicité en général": "Office", + "Service de publicité en général": cte.MEDIUM_OFFICE, "Service de recherche de développement et d'essais": cte.SECONDARY_SCHOOL, "Service de remplacement de pièces et d'accessoires d'automobiles (amortisseurs silencieux toits ouvrants glacespare-brises...)": cte.WAREHOUSE, "Service de revêtement en asphalte et en bitume": cte.WAREHOUSE, "Service de réparation d'automobiles (garage) sans pompes à essence(5531)": cte.WAREHOUSE, "Service de réparation d'autres véhicules légers": cte.WAREHOUSE, "Service de réparation de véhicules légers motorisés (motocyclettemotoneige véhicule tout terrain)": cte.WAREHOUSE, - "Service de réparation et d'entretien de machines et de matériel d'usage commercial et industriel": "Office", - "Service de réparation et d'entretien de matériel informatique": "Office", + "Service de réparation et d'entretien de machines et de matériel d'usage commercial et industriel": cte.WAREHOUSE, + "Service de réparation et d'entretien de matériel informatique": cte.COMMERCIAL, "Service de réparation et d'entretien de systèmes de plomberieschauffageventilation et climatisation.(entrepreneur spécialisé)": cte.WAREHOUSE, "Service de réparation et d'entretien de véhicules lourds": cte.WAREHOUSE, "Service de réparation et de rembourrage de meubles": cte.WAREHOUSE, @@ -421,8 +420,8 @@ class MontrealFunctionToHubFunction: "Service de vétérinaires et d'hôpital pour animaux de ferme": cte.OUT_PATIENT_HEALTH_CARE, "Service dentaire (inclus chirurgie et hygiène)": cte.OUT_PATIENT_HEALTH_CARE, "Service en santé mentale (cabinet) (comprend tous services professionnelspsychiatre psychologuepsychanalyste)": cte.OUT_PATIENT_HEALTH_CARE, - "Service en travaux de fondation et de structures en béton (entrepreneur spécialisé)": "Office", - "Service informatique (location ou utilisation partagée services auxiliaires programmation planification et analyse de système)": "Office", + "Service en travaux de fondation et de structures en béton (entrepreneur spécialisé)": cte.WAREHOUSE, + "Service informatique (location ou utilisation partagée services auxiliaires programmation planification et analyse de système)": cte.MEDIUM_OFFICE, "Service médical (cabinet de médecins et chirurgiens spécialisés)": cte.OUT_PATIENT_HEALTH_CARE, "Service photographique (incluant les services commerciaux)": cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD, "Service pour l'entretien ménager": cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD, @@ -439,10 +438,10 @@ class MontrealFunctionToHubFunction: "Stationnement extérieur (condo)": cte.NON_HEATED, "Stationnement intérieur ( condo non résidentiel)": cte.WAREHOUSE, "Stationnement intérieur (condo)": cte.WAREHOUSE, - "Studio d'enregistrement du son (disque cassette et disque compact)": "Office", - "Studio de production de filmsde vidéos ou de publicités (ne comprends pas le laboratoire de production)": "Office", - "Studio de télévision (sans public)": "Office", - "Syndicat et organisation similaire": "Office", + "Studio d'enregistrement du son (disque cassette et disque compact)": cte.MEDIUM_OFFICE, + "Studio de production de filmsde vidéos ou de publicités (ne comprends pas le laboratoire de production)": cte.MEDIUM_OFFICE, + "Studio de télévision (sans public)": cte.MEDIUM_OFFICE, + "Syndicat et organisation similaire": cte.MEDIUM_OFFICE, "Terminus maritime (passagers) incluant les gares de traversiers": cte.WAREHOUSE, "Terrain de golf (avec chalet et autres aménagements sportifs)": cte.NON_HEATED, "Terrain de sport (jeux et pistes pour compétitions et sportgradins)": cte.NON_HEATED, @@ -546,10 +545,129 @@ class MontrealFunctionToHubFunction: "Mausolée": cte.NON_HEATED, "Auberge ou gîte touristique (Hôtel à caractère familial, d'au plus 3 étages en hauteur de bâtiment)": cte.HOTEL, "Service de garderie (prématernelle, moins de 50 % de poupons)": cte.PRIMARY_SCHOOL, - "Église, synagogue, mosquée et temple": cte.CONVENTION_CENTER - - + "Église, synagogue, mosquée et temple": cte.CONVENTION_CENTER, + "Station libre-service, ou avec service et dépanneur sans réparation de véhicules automobiles": cte.WAREHOUSE, + "Service de buanderie, de nettoyage à sec et de teinture (sauf les tapis)": cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD, + "Service bancaire (dépôts et prêts, incluant banque à charte)": cte.COMMERCIAL, + "Restaurant et établissement avec service complet (avec terrasse) - Établissements avec permis alcool, inclus pub,café et brasserie": cte.FULL_SERVICE_RESTAURANT, + "Restaurant et établissement avec service complet (sans terrasse) -Établissements avec permis alcool, inclus pub,café et brasserie": cte.FULL_SERVICE_RESTAURANT, + "Autres services immobiliers, financiers et d'assurance": cte.COMMERCIAL, + "Résidence de tourisme, appartement, maison ou chalet (meublé et équipé pour repas)": cte.RESIDENTIAL, + "Salon de beauté (maquillage, manucure, etc..)": cte.COMMERCIAL, + "Service de buanderie et de nettoyage à sec (libre-service)": cte.COMMERCIAL, + "Association civique, sociale et fraternelle": cte.COMMERCIAL, + "Vente en gros d'automobiles et autres véhicules automobiles neufs ou d'occasions, incluent VR)": cte.WAREHOUSE, + "Autres services de soutien aux entreprises": cte.COMMERCIAL, + "Vente au détail de vêtements pour toute la famille": cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD, + "Vente au détail de bijoux": cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD, + "Service d'avocats": cte.MEDIUM_OFFICE, + "Service informatique (location ou utilisation partagée, services auxiliaires programmation planification et analyse de système)": cte.MEDIUM_OFFICE, + "Centre d'entraide et de ressources communautaires (inclus ressources d'hébergement, de meubles et d'alimentation)": cte.COMMERCIAL, + "Service de comptabilité, de vérification et de tenue de livre": cte.MEDIUM_OFFICE, + "Autres transports, communications et services publics (infrastructure)": cte.WAREHOUSE, + "Autres institutions de formation spécialisée (inclus écoles de langues, de couture, d'arts martiaux, de combats et autres)": cte.SECONDARY_SCHOOL, + "Chemin de fer (sauf train touristique, aiguillage et cour de triage)": cte.WAREHOUSE, + "Service d'agence de placement": cte.COMMERCIAL, + "Espace de plancher inoccupé dont l'usage serait la vente au détail": cte.NON_HEATED, + "Industrie de produits en plastique stratifié, sous pression ou renforcé": cte.INDUSTRY, + "Studio de production de films, de vidéos ou de publicités (ne comprends pas le laboratoire de production)": cte.MOTION_PICTURE_THEATRE, + "Industrie de la fabrication de supports d'enregistrement, de la reproduction du son et des instruments de musique": cte.INDUSTRY, + "Vente au détail du café, du thé, d'épices et d'aromates": cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD, + "Station libre-service, ou avec service sans réparation de véhicules automobiles": cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD, + "Vente au détail de produits de la boulangerie et de la pâtisserie (non manufacturés sur place)": cte.RETAIL_SHOP_WITH_REFRIGERATED_FOOD, + "Vente au détail de serrures, de clés et d'accessoires": cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD, + "Autres activités de vente au détail de vêtements, comme les accessoires": cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD, + "Vente en gros d'équipements et de pièces pour la réfrigération, ventilation, la climatisation et le chauffage (système combiné)": cte.WAREHOUSE, + "Service de réparation de véhicules légers motorisés (motocyclette, motoneige, véhicule tout terrain)": cte.WAREHOUSE, + "Service de location de camions, de remorques utilitaires et de véhicules de plaisance": cte.WAREHOUSE, + "Vente au détail d'autres articles de ferme": cte.RETAIL_SHOP_WITH_REFRIGERATED_FOOD, + "Salon d'esthétique (épilation, traitement de la peau)": cte.COMMERCIAL, + "Service de location de films, de jeux vidéos et de matériel audiovisuel": cte.RETAIL_SHOP_WITH_REFRIGERATED_FOOD, + "Vente en gros de vêtements, de lingerie, de bas et d'accessoires": cte.WAREHOUSE, + "Service d'entretien de chaussures et d'articles de cuir (cordonnerie)": cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD, + "Vente au détail de lingerie pour enfants": cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD, + "Vente au détail, magasin à rayons": cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD, + "Vente au détail de vêtements et d'articles usagés, friperies (sauf le marché aux puces)": cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD, + "Entreposage du mobilier et d'appareils ménagers, incluant les mini-entrepôts": cte.WAREHOUSE, + "Service de construction non résidentielle, industrielle (entrepreneur général)": cte.WAREHOUSE, + "Immeuble à temps partagé («time share») Propriété ou copropriété ou groupe d'usufruitier ont chacun droit de jouissance, périodique et successif.": cte.COMMERCIAL, + "Autres activités récréatives": cte.EVENT_LOCATION, + "Industrie de produits de boulangerie commerciale, de produits de boulangerie congelés et de pâtisseries": cte.INDUSTRY, + "Studio d'enregistrement du son (disque, cassette et disque compact)": cte.COMMERCIAL, + "Autres services de soins paramédicaux": cte.RETAIL_SHOP_WITH_REFRIGERATED_FOOD, + "Studio de radiodiffusion (sans public)": cte.COMMERCIAL, + "Autres présentations d'objets ou d'animaux": cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD, + "Autres étendues d'eau": cte.WAREHOUSE, + "Maison d'agents, de courtiers et de services d'administration des biens-fonds": cte.MEDIUM_OFFICE, + "Industrie de l'édition du livre": cte.INDUSTRY, + "Vente au détail ou location d'articles,d'accessoires de scène et de costumes": cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD, + "École de beaux-arts et de musique (exclus arts publicitaires, arts graphiques et photographie publicitaire)": cte.SECONDARY_SCHOOL, + "Vente au détail de peinture, de verre et de papier tenture": cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD, + "Agence et courtier d'assurances": cte.MEDIUM_OFFICE, + "Centre de santé (inclus saunas, spas et bains thérapeutiques ou turcs)": cte.HEALTH_CARE, + "Établissement dont l'activité principale est la danse (discothèque avec service alcool, boite de nuit) sans alcool code 7397": cte.QUICK_SERVICE_RESTAURANT, + "Vente au détail de pneus, de batteries et d'accessoires": cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD, + "Salle et terrain de squash, de racquetball et de tennis": cte.WAREHOUSE, + "Service de télécommunication sans fil (appareil mobile, sauf par Internet)": cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD, + "Centre de recherche en science physique et chimique (inclus science optique)": cte.UNIVERSITY, + "Association, union ou coop d'épargne et de prêt (inclus caisses populaires locales)": cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD, + "Industrie du meuble et d'articles d'ameublement pour hôtels, restaurants et institutions": cte.INDUSTRY, + "Service d'affichage à l'extérieur": cte.NON_HEATED, + "Service de traitement pour automobiles (antirouille, etc.)": cte.INDUSTRY, + "Vente au détail de revêtements de planchers et de murs (bois franc, plancher flottant, carreaux céramiques, tapisserie)": cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD, + "Vente au détail de livres et de journaux": cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD, + "Autres industries du laminage, du moulage et de l'extrusion de métaux non-ferreux": cte.INDUSTRY, + "Vente au détail d'appareils ménagers": cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD, + "Service de plomberie, de chauffage, de climatisation et de ventilation (entrepreneur spécialisé)": cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD, + "Vente au détail de radios, de téléviseurs, systèmes de son et appareils électroniques": cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD, + "Vente au détail, clubs de gros et hypermarchés (entrepôt-club)": cte.STRIP_MALL, + "Conserverie, marinage, saumurage et séchage de fruits et de légumes": cte.RETAIL_SHOP_WITH_REFRIGERATED_FOOD, + "Industrie de l'étirage, de l'extrusion et alliage de l'aluminium, fabriqué à partir d'aluminium acheté": cte.INDUSTRY, + "Restaurant et établissement offrant des repas à libre-service (cafétéria, cantine)": cte.QUICK_SERVICE_RESTAURANT, + "Pressage de vêtements": cte.COMMERCIAL, + "Vente au détail d'articles, d'accessoires d'aménagement paysager et de jardin": cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD, + "Planétarium": cte.MUSEUM, + "Industrie de ventilateurs, de soufflantes et de purificateurs d'air industriels et commerciaux": cte.INDUSTRY, + "Service de pose de portes, de fenêtres et de panneaux de verre": cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD, + "Association de personnes exerçant une même profession ou une même activité": cte.MEDIUM_OFFICE, + "Service de remplacement de pièces et d'accessoires d'automobiles (amortisseurs, silencieux,toits ouvrants, glaces, pare-brises...)": cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD, + "Service d'hébergement des données (sites Web, diffusion audio et vidéo en continu, services d'application)": cte.DATACENTER, + "Vente au détail de produits naturels et aliments de régime": cte.RETAIL_SHOP_WITH_REFRIGERATED_FOOD, + "Autres activités de vente au détail reliées aux automobiles, aux embarcations, aux avions et à leurs accessoires": cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD, + "Autres lieux d'amusement": cte.EVENT_LOCATION, + "Vente en gros d'appareils et d'équipements électriques, de fils et de matériel électronique de construction": cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD, + "Industrie de peinture, de teinture et de vernis": cte.INDUSTRY, + "Autres industries de l'impression et de l'édition (combinées)": cte.INDUSTRY, + "Vente en gros d'équipements et de pièces de machinerie commerciale,industrielle ou agricole (incluant machinerie lourde)": cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD, + "Industrie de lingerie, de vêtements de détente et de vêtements de nuit pour femmes et filles": cte.INDUSTRY, + "Vente au détail d'équipements de plomberie, de chauffage, de ventilation, de climatisation et de foyer": cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD, + "Autres industries de produits minéraux non métalliques": cte.INDUSTRY, + "Entreprise d'excavation, de nivellement, de défrichage et installation de fosses septiques": cte.NON_HEATED, + "Vente au détail, fournitures pour la maison et l'auto": cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD, + "Industrie d'armoires, de placards de cuisine et de coiffeuses de salle de bains en bois": cte.INDUSTRY, + "Terrain de sport (jeux et pistes pour compétitions et sport, gradins)": cte.SPORTS_LOCATION, + "Vente au détail de piscines, de spas et leurs accessoires": cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD, + "Service en santé mentale (cabinet) (comprend tous services professionnels, psychiatre,psychologue, psychanalyste)": cte.HEALTH_CARE, + "Service de construction de routes, de rues et de ponts,de trottoirs et de pistes (entrepreneur général)": cte.NON_HEATED, + "Vente en gros d'appareils électriques, de téléviseurs et de radios": cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD, + "Vente au détail de motocyclettes, de motoneiges et de leurs accessoires": cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD, + "Industrie du meuble rembourré résidentiel (rembourrage, service de réparation, voir 6423)": cte.INDUSTRY, + "Vente au détail de jouets et d'articles de jeux": cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD, + "Industrie du laminage, de l'étirage et de l'extrusion du cuivre et de ses alliages": cte.INDUSTRY, + "Archives (incluant cinémathèque, vidéothèque)": cte.WAREHOUSE_REFRIGERATED, + "Service de recherche, de développement et d'essais": cte.UNIVERSITY, + "Industrie de tapis, carpettes et moquettes": cte.INDUSTRY, + "Industrie du revêtement métallique, sur commande": cte.INDUSTRY, + "Service de réparation et d'entretien de systèmes de plomberies,chauffage, ventilation et climatisation.(entrepreneur spécialisé)": cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD, + "Salle de réunions, centre de conférence et congrès": cte.CONVENTION_CENTER, + "Vente en gros d'autres médicaments, de produits chimiques et de produits connexes": cte.RETAIL_SHOP_WITH_REFRIGERATED_FOOD, + "Vente au détail d'armoires de coiffeuses et de meubles d'appoint": cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD, + "Industrie de chaudières, d'échangeurs de chaleur et de plaques métalliques": cte.INDUSTRY, + "Industrie du clichage, de la composition de la reliure et de la lithographie": cte.INDUSTRY, + "Service de construction non résidentielle, commerciale et institutionnelle (entrepreneur général)": cte.MEDIUM_OFFICE, + "Centre d'entreposage de produits pétroliers (pétrole brut, gaz pétrole liquéfié, mazout domestique et autres produits raffinés)": cte.WAREHOUSE, + "École à caractère familial (exploité par une personne physique dans sa résidence, moins de 15 élèves)": cte.PRIMARY_SCHOOL } @property diff --git a/hub/imports/results/insel_heatpump_energy_demand.py b/hub/imports/results/insel_heatpump_energy_demand.py new file mode 100644 index 00000000..98cb439f --- /dev/null +++ b/hub/imports/results/insel_heatpump_energy_demand.py @@ -0,0 +1,38 @@ +""" +Insel Heap pump energy demand and fossil fuel consumption +SPDX - License - Identifier: LGPL - 3.0 - or -later +Copyright © 2023 Concordia CERC group +Project Coder peter.yefi@gmail.cm +""" + +from pathlib import Path +import pandas as pd + + +class InselHeatPumpEnergyDemand: + """ + Import Energy demand and fossil fuel consumption results + """ + def __init__(self, city, base_path, hp_model): + """ + :param city: the city + :param base_path: the insel simulation output file + :param hp_model: the heatpump model for both air source and water to water + """ + self._city = city + self._hp_model = hp_model + with open(Path(base_path).resolve()) as csv_file: + df = pd.read_csv(csv_file) + self._monthly_electricity_demand = df.iloc[:, 1] + self._monthly_fossil_fuel_consumption = df.iloc[:, 2] + + def enrich(self): + for energy_system in self._city.energy_systems: + if energy_system.air_source_hp is not None: + if energy_system.air_source_hp.model == self._hp_model: + energy_system.air_source_hp.hp_monthly_fossil_consumption = self._monthly_fossil_fuel_consumption + + if energy_system.water_to_water_hp is not None: + if energy_system.water_to_water_hp.model == self._hp_model: + energy_system.water_to_water_hp.hp_monthly_electricity_demand = self._monthly_electricity_demand + diff --git a/hub/imports/results_factory.py b/hub/imports/results_factory.py index afa90fb6..62adf124 100644 --- a/hub/imports/results_factory.py +++ b/hub/imports/results_factory.py @@ -11,13 +11,23 @@ from hub.helpers.utils import validate_import_export_type from hub.hub_logger import logger from hub.imports.results.simplified_radiosity_algorithm import SimplifiedRadiosityAlgorithm from hub.imports.results.insel_monthly_energry_balance import InselMonthlyEnergyBalance +from hub.imports.results.insel_heatpump_energy_demand import InselHeatPumpEnergyDemand class ResultFactory: """ - UsageFactory class + ResultFactory class """ - def __init__(self, handler, city, base_path=None): + + def __init__(self, handler, city, base_path=None, hp_model=None): + """ + + :param handler: pointer to results class to be called + :param city: the city object + :param base_path: the path to result output file + :param hp_model: (optional) the heat pump model for which + results are being retrieved + """ if base_path is None: base_path = Path(Path(__file__).parent.parent / 'data/results') self._handler = '_' + handler.lower().replace(' ', '_') @@ -28,6 +38,7 @@ class ResultFactory: raise Exception(err_msg) self._city = city self._base_path = base_path + self._hp_model = hp_model def _sra(self): """ @@ -35,6 +46,13 @@ class ResultFactory: """ SimplifiedRadiosityAlgorithm(self._city, self._base_path).enrich() + def _heat_pump(self): + """ + Enrich the city (energy system specifically) with heat pump insel simulation + results + """ + InselHeatPumpEnergyDemand(self._city, self._base_path, self._hp_model).enrich() + def _insel_meb(self): """ Enrich the city with insel monthly energy balance results diff --git a/hub/imports/user_factory.py b/hub/imports/user_factory.py index 3d900c1f..f4954189 100644 --- a/hub/imports/user_factory.py +++ b/hub/imports/user_factory.py @@ -4,7 +4,7 @@ SPDX - License - Identifier: LGPL - 3.0 - or -later Copyright © 2022 Concordia CERC group Project CoderPeter Yefi peteryefi@gmail.com """ -from hub.persistence import UserRepo +from hub.persistence import User from hub.persistence import UserRoles @@ -14,7 +14,7 @@ class UserFactory: """ def __init__(self, db_name, app_env, dotenv_path): - self._user_repo = UserRepo(db_name=db_name, app_env=app_env, dotenv_path=dotenv_path) + self._user_repo = User(db_name=db_name, app_env=app_env, dotenv_path=dotenv_path) def create_user(self, name: str, email: str, password: str, role: UserRoles): """ diff --git a/hub/persistence/repositories/user.py b/hub/persistence/repositories/user.py index dfa797d6..87005a4a 100644 --- a/hub/persistence/repositories/user.py +++ b/hub/persistence/repositories/user.py @@ -9,6 +9,7 @@ from hub.persistence import Repository from sqlalchemy.exc import SQLAlchemyError from sqlalchemy import select from hub.persistence.models import User as Model +from hub.persistence.models import Application as ApplicationModel from hub.persistence.models import UserRoles from hub.helpers.auth import Auth from typing import Union, Dict @@ -99,14 +100,14 @@ class User(Repository): except SQLAlchemyError as err: logger.error(f'Error while fetching user by name and application: {err}') - def get_by_name_application_and_password(self, name: str, password: str, application_id: int) -> [Model]: + def get_by_name_application_id_and_password(self, name: str, password: str, application_id: int) -> [Model]: """ Fetch user based on the email and password :param name: User name :param password: User password :param application_id: User password - :return: [User] with the provided email and password + :return: [User] """ try: user = self.session.execute( @@ -115,6 +116,22 @@ class User(Repository): if user: if Auth.check_password(password, user[0].password): return user[0] - return {'message': 'invalid login information'} except SQLAlchemyError as err: logger.error(f'Error while fetching user by email: {err}') + + def get_by_name_application_uuid_and_password(self, name: str, password: str, application_uuid: str) -> [Model]: + """ + Fetch user based on the email and password + :param name: User name + :param password: User password + :param application_uuid: Application uuid + + :return: [User] + """ + try: + application = self.session.execute( + select(ApplicationModel).where(ApplicationModel.application_uuid == application_uuid) + ).first() + return self.get_by_name_application_id_and_password(name, password, application[0].id) + except SQLAlchemyError as err: + logger.error(f'Error while fetching user by name: {err}') diff --git a/hub/unittests/test_heat_pump_results.py b/hub/unittests/test_heat_pump_results.py new file mode 100644 index 00000000..fa7d2d15 --- /dev/null +++ b/hub/unittests/test_heat_pump_results.py @@ -0,0 +1,74 @@ +""" +Test EnergySystemsFactory and various heatpump models +SPDX - License - Identifier: LGPL - 3.0 - or -later +Copyright © 2023 Concordia CERC group +Project Coder Peter Yefi peteryefi@gmail.com +""" +from unittest import TestCase +from hub.imports.geometry_factory import GeometryFactory +from hub.imports.energy_systems_factory import EnergySystemsFactory +from hub.exports.energy_systems_factory import EnergySystemsExportFactory +from hub.imports.results_factory import ResultFactory +import os +from pandas.core.series import Series + +# User defined paramenters +user_input = { + 'StartYear': 2020, + 'EndYear': 2021, + 'MaximumHPEnergyInput': 8000, + 'HoursOfStorageAtMaxDemand': 1, + 'BuildingSuppTemp': 40, + 'TemperatureDifference': 15, + 'FuelLHV': 47100, + 'FuelPrice': 0.12, + 'FuelEF': 1887, + 'FuelDensity': 0.717, + 'HPSupTemp': 60 +} + + +class TestHeatPumpResults(TestCase): + """ + TestHeatPumpResults + """ + + def setUp(self) -> None: + """ + Test setup + :return: None + """ + city_file = "tests_data/C40_Final.gml" + self._output_path = "tests_data/as_user_output.csv" + self._city = GeometryFactory('citygml', path=city_file).city + EnergySystemsFactory('air source hp', self._city).enrich() + + def test_air_source_series_heat_pump_012_results(self): + EnergySystemsExportFactory(city=self._city, user_input=user_input, hp_model='012', + output_path=self._output_path).export() + ResultFactory('heat pump', self._city, self._output_path, '012').enrich() + + for energy_system in self._city.energy_systems: + self.assertIsNone(energy_system.water_to_water_hp) + if energy_system.air_source_hp.model == '012': + self.assertIsInstance(energy_system.air_source_hp.hp_monthly_fossil_consumption, Series) + self.assertEqual(energy_system.air_source_hp.hp_monthly_fossil_consumption.iloc[5], 1.51325583) + self.assertEqual(energy_system.air_source_hp.hp_monthly_fossil_consumption.iloc[12], 35.853598782915) + + def test_air_source_series_heat_pump_015_results(self): + EnergySystemsExportFactory(city=self._city, user_input=user_input, hp_model='140', + output_path=self._output_path).export() + ResultFactory('heat pump', self._city, self._output_path, '140').enrich() + + for energy_system in self._city.energy_systems: + self.assertIsNone(energy_system.water_to_water_hp) + if energy_system.air_source_hp.model == '140': + self.assertIsInstance(energy_system.air_source_hp.hp_monthly_fossil_consumption, Series) + self.assertEqual(energy_system.air_source_hp.hp_monthly_fossil_consumption.iloc[0], 7.91282225) + self.assertEqual(energy_system.air_source_hp.hp_monthly_fossil_consumption.iloc[2], 0.068873927) + + def tearDown(self) -> None: + try: + os.remove(self._output_path) + except OSError: + pass diff --git a/hub/version.py b/hub/version.py index 0676f8b8..c3913bcd 100644 --- a/hub/version.py +++ b/hub/version.py @@ -1 +1 @@ -__version__ = '0.1.7.6' +__version__ = '0.1.7.8' diff --git a/setup.py b/setup.py index c65667e9..0053ffc1 100644 --- a/setup.py +++ b/setup.py @@ -67,7 +67,6 @@ setup( 'hub.imports', 'hub.imports.construction', 'hub.imports.construction.helpers', - 'hub.imports.construction.data_classes', 'hub.imports.energy_systems', 'hub.imports.geometry', 'hub.imports.geometry.citygml_classes', @@ -87,23 +86,23 @@ setup( ('hub/config', glob.glob('hub/config/*.ini')), ('hub/catalog_factories/greenery/ecore_greenery', glob.glob('hub/catalog_factories/greenery/ecore_greenery/*.ecore')), ('hub/data/construction.', glob.glob('hub/data/construction/*')), - ('hub/data/customized_imports/', glob.glob('hub/data/customized_imports/*.xml')), - ('hub/data/energy_systems/', glob.glob('hub/data/energy_systems/*.xml')), - ('hub/data/energy_systems/', glob.glob('hub/data/energy_systems/*.insel')), - ('hub/data/energy_systems/', glob.glob('hub/data/energy_systems/*.xlsx')), - ('hub/data/energy_systems/*', glob.glob('hub/data/energy_systems/*.txt')), - ('hub/data/energy_systems/*', glob.glob('hub/data/energy_systems/*.yaml')), - ('hub/data/greenery/', glob.glob('hub/data/greenery/*.xml')), - ('hub/data/life_cycle_assessment/', glob.glob('hub/data/life_cycle_assessment/*.xml')), - ('hub/data/schedules/', glob.glob('hub/data/schedules/*.xml')), - ('hub/data/schedules/', glob.glob('hub/data/schedules/*.xlsx')), - ('hub/data/schedules/idf_files/', glob.glob('hub/data/schedules/idf_files/*.idf')), - ('hub/data/sensors/', glob.glob('hub/data/sensors/*.json')), - ('hub/data/usage/', glob.glob('hub/data/usage/*.xml')), - ('hub/data/usage/', glob.glob('hub/data/usage/*.xlsx')), - ('hub/data/weather/', glob.glob('hub/data/weather/*.dat')), - ('hub/data/weather/epw/', glob.glob('hub/data/weather/epw/*.epw')), - ('hub/data/weather/', glob.glob('hub/data/weather/*.dat')), + ('hub/data/customized_imports', glob.glob('hub/data/customized_imports/*.xml')), + ('hub/data/energy_systems', glob.glob('hub/data/energy_systems/*.xml')), + ('hub/data/energy_systems', glob.glob('hub/data/energy_systems/*.insel')), + ('hub/data/energy_systems', glob.glob('hub/data/energy_systems/*.xlsx')), + ('hub/data/energy_systems', glob.glob('hub/data/energy_systems/*.txt')), + ('hub/data/energy_systems', glob.glob('hub/data/energy_systems/*.yaml')), + ('hub/data/greenery', glob.glob('hub/data/greenery/*.xml')), + ('hub/data/life_cycle_assessment', glob.glob('hub/data/life_cycle_assessment/*.xml')), + ('hub/data/schedules', glob.glob('hub/data/schedules/*.xml')), + ('hub/data/schedules', glob.glob('hub/data/schedules/*.xlsx')), + ('hub/data/schedules/idf_files', glob.glob('hub/data/schedules/idf_files/*.idf')), + ('hub/data/sensors', glob.glob('hub/data/sensors/*.json')), + ('hub/data/usage', glob.glob('hub/data/usage/*.xml')), + ('hub/data/usage', glob.glob('hub/data/usage/*.xlsx')), + ('hub/data/weather', glob.glob('hub/data/weather/*.dat')), + ('hub/data/weather/epw', glob.glob('hub/data/weather/epw/*.epw')), + ('hub/data/weather', glob.glob('hub/data/weather/*.dat')), ('hub/exports/building_energy/idf_files', glob.glob('hub/exports/building_energy/idf_files/*.idf')), ('hub/exports/building_energy/idf_files', glob.glob('hub/exports/building_energy/idf_files/*.idd')), ('hub/helpers/data', glob.glob('hub/helpers/data/quebec_to_hub.json'))