mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-06-08 11:17:27 +00:00
added condition data to router
This commit is contained in:
parent
73b6fb2b70
commit
24508b2a84
7 changed files with 68 additions and 16 deletions
|
|
@ -166,6 +166,7 @@ class Property:
|
|||
)
|
||||
self.floor_level = None
|
||||
self.number_of_windows = None
|
||||
self.windows_area = None
|
||||
self.solar_pv_percentage = None
|
||||
|
||||
self.current_adjusted_energy = None
|
||||
|
|
@ -707,17 +708,20 @@ class Property:
|
|||
# Today's costs
|
||||
todays_heating_cost = energy_consumption_client.convert_cost_to_today(
|
||||
original_cost=float(self.data["heating-cost-current"]),
|
||||
lodgement_date=pd.Timestamp(self.epc_record.prepared_epc["lodgement_date"])
|
||||
lodgement_date=pd.Timestamp(self.epc_record.prepared_epc["lodgement_date"]).tz_localize(None)
|
||||
)
|
||||
todays_hot_water_cost = energy_consumption_client.convert_cost_to_today(
|
||||
original_cost=float(self.data["hot-water-cost-current"]),
|
||||
lodgement_date=pd.Timestamp(self.epc_record.prepared_epc["lodgement_date"])
|
||||
lodgement_date=pd.Timestamp(self.epc_record.prepared_epc["lodgement_date"]).tz_localize(None)
|
||||
)
|
||||
todays_lighting_cost = energy_consumption_client.convert_cost_to_today(
|
||||
original_cost=float(self.data["lighting-cost-current"]),
|
||||
lodgement_date=pd.Timestamp(self.epc_record.prepared_epc["lodgement_date"])
|
||||
lodgement_date=pd.Timestamp(self.epc_record.prepared_epc["lodgement_date"]).tz_localize(None)
|
||||
)
|
||||
|
||||
# If we have the kwh figures, we don't need to predict them
|
||||
condition_data = self.energy_assessment_condition_data.copy()
|
||||
|
||||
scoring_df = pd.DataFrame([self.epc_record.prepared_epc])
|
||||
# Change columns from underscores to hyphens
|
||||
scoring_df.columns = [
|
||||
|
|
@ -727,13 +731,20 @@ class Property:
|
|||
scoring_df[col] = None
|
||||
|
||||
energy_consumption_client.data = None
|
||||
heating_prediction = energy_consumption_client.score_new_data(
|
||||
new_data=scoring_df, target="heating_kwh"
|
||||
)[0]
|
||||
|
||||
hot_water_prediction = energy_consumption_client.score_new_data(
|
||||
new_data=scoring_df, target="hot_water_kwh"
|
||||
)[0]
|
||||
heating_prediction = (
|
||||
float(condition_data["space_heating_kwh"]) if condition_data["space_heating_kwh"]
|
||||
else energy_consumption_client.score_new_data(
|
||||
new_data=scoring_df, target="heating_kwh"
|
||||
)[0]
|
||||
)
|
||||
|
||||
hot_water_prediction = (
|
||||
float(condition_data["water_heating_kwh"]) if condition_data["water_heating_kwh"]
|
||||
else energy_consumption_client.score_new_data(
|
||||
new_data=scoring_df, target="hot_water_kwh"
|
||||
)[0]
|
||||
)
|
||||
|
||||
# We convert the lighting cost into kwh, just using the price cap
|
||||
lighting_kwh = float(self.data["lighting-cost-current"]) / AnnualBillSavings.ELECTRICITY_PRICE_CAP
|
||||
|
|
@ -1040,13 +1051,14 @@ class Property:
|
|||
medians across the EPC data
|
||||
:return:
|
||||
"""
|
||||
|
||||
# TODO: These functions should work on an EPCRecord object, so that the format is more standardised.
|
||||
# They could also be added as attributes to the EPC Record
|
||||
|
||||
# Many of these pieces of information are now contained in the condition data
|
||||
condition_data = self.energy_assessment_condition_data.copy()
|
||||
|
||||
# We can update the number of floors if we have this information in the condition data
|
||||
self.number_of_floors = int(self.energy_assessment_condition_data["number_of_floors"]) \
|
||||
if condition_data["number_of_floors"] is not None \
|
||||
else self.number_of_floors
|
||||
|
||||
self.perimeter = float(self.energy_assessment_condition_data["perimeter"]) \
|
||||
if condition_data["perimeter"] is not None \
|
||||
else estimate_perimeter(
|
||||
|
|
@ -1054,14 +1066,18 @@ class Property:
|
|||
num_rooms=self.number_of_rooms / self.number_of_floors
|
||||
)
|
||||
|
||||
self.insulation_wall_area = estimate_external_wall_area(
|
||||
self.insulation_wall_area = float(self.energy_assessment_condition_data["insulation_wall_area"]) \
|
||||
if condition_data["insulation_wall_area"] is not None \
|
||||
else estimate_external_wall_area(
|
||||
num_floors=self.number_of_floors,
|
||||
floor_height=self.floor_height,
|
||||
perimeter=self.perimeter,
|
||||
built_form=self.data["built-form"],
|
||||
)
|
||||
|
||||
self.insulation_floor_area = self.floor_area / self.number_of_floors
|
||||
self.insulation_floor_area = float(self.energy_assessment_condition_data["main_dwelling_ground_floor_area"]) \
|
||||
if condition_data["main_dwelling_ground_floor_area"] is not None \
|
||||
else self.floor_area / self.number_of_floors
|
||||
|
||||
self.pitched_roof_area = esimtate_pitched_roof_area(
|
||||
floor_area=self.insulation_floor_area, floor_height=self.floor_height
|
||||
|
|
@ -1163,7 +1179,11 @@ class Property:
|
|||
:return:
|
||||
"""
|
||||
|
||||
self.number_of_windows = estimate_windows(
|
||||
condition_data = self.energy_assessment_condition_data.copy()
|
||||
|
||||
self.number_of_windows = int(condition_data["number_of_windows"]) \
|
||||
if condition_data["number_of_windows"] is not None \
|
||||
else estimate_windows(
|
||||
property_type=self.data["property-type"],
|
||||
built_form=self.data["built-form"],
|
||||
construction_age_band=self.construction_age_band,
|
||||
|
|
@ -1171,6 +1191,10 @@ class Property:
|
|||
number_habitable_rooms=self.number_of_rooms,
|
||||
)
|
||||
|
||||
self.windows_area = float(condition_data["windows_area"]) \
|
||||
if condition_data["windows_area"] is not None \
|
||||
else None
|
||||
|
||||
def set_solar_panel_area(self, photo_supply_lookup, floor_area_decile_thresholds):
|
||||
"""
|
||||
Sets the approximate area of the solar panels
|
||||
|
|
|
|||
|
|
@ -119,6 +119,9 @@ class EnergyAssessment(Base):
|
|||
cylinder_insulation_type = Column(Text)
|
||||
cylinder_insulation_thickness = Column(Integer)
|
||||
cylinder_thermostat = Column(Boolean)
|
||||
main_dwelling_ground_floor_area = Column(Float)
|
||||
number_of_windows = Column(Integer)
|
||||
windows_area = Column(Float)
|
||||
|
||||
EPC_KEYS = [
|
||||
'low_energy_fixed_light_count', 'address', 'uprn_source', 'floor_height', 'heating_cost_potential',
|
||||
|
|
|
|||
|
|
@ -515,6 +515,8 @@ async def trigger_plan(body: PlanTriggerRequest):
|
|||
# )
|
||||
print("Implement me")
|
||||
|
||||
# TODO: We can set the pitched roof area based on the results of the solar api!
|
||||
|
||||
logger.info("Getting components and epc recommendations")
|
||||
recommendations = {}
|
||||
recommendations_scoring_data = []
|
||||
|
|
|
|||
|
|
@ -102,6 +102,7 @@ class EnergyConsumptionModel:
|
|||
# We also retrieve the newest retail price comparison data which comes from Ofgem:
|
||||
# https://www.ofgem.gov.uk/energy-data-and-research/data-portal/retail-market-indicators
|
||||
# We use the detail price comparison by company and tariff type data
|
||||
print("Reading retail price comparison - make sure this is up-to-date")
|
||||
self.read_retail_price_comparison()
|
||||
|
||||
def read_retail_price_comparison(self):
|
||||
|
|
|
|||
|
|
@ -366,6 +366,16 @@ class XmlParser:
|
|||
|
||||
self.insulation_wall_area = self.get_insulation_wall_area()
|
||||
|
||||
# We pull this out which is used as the insulation floor area
|
||||
main_dwelling_ground_floor_area = [
|
||||
f for f in self.floor_dimensions if f["building_part_identifier"] == "Main Dwelling" and f["floor"] == "0"
|
||||
][0]["total_floor_area"]
|
||||
|
||||
main_dwelling_windows = [w for w in self.windows if w["window_location"] == "0"]
|
||||
|
||||
number_of_windows = len(main_dwelling_windows)
|
||||
windows_area = sum([float(w["window_area"]) for w in main_dwelling_windows])
|
||||
|
||||
boolean_lookup = {
|
||||
"true": True,
|
||||
"false": False,
|
||||
|
|
@ -400,6 +410,9 @@ class XmlParser:
|
|||
"cylinder_insulation_type": cylinder_insulation_type[self.get_node_value('Cylinder-Insulation-Type')],
|
||||
"cylinder_insulation_thickness": int(self.get_node_value('Cylinder-Insulation-Thickness')),
|
||||
"cylinder_thermostat": boolean_lookup[self.get_node_value('Cylinder-Thermostat')],
|
||||
"main_dwelling_ground_floor_area": float(main_dwelling_ground_floor_area),
|
||||
"number_of_windows": int(number_of_windows),
|
||||
"windows_area": float(windows_area),
|
||||
}
|
||||
|
||||
def get_node_value(self, tag_name):
|
||||
|
|
|
|||
|
|
@ -58,6 +58,11 @@ def main():
|
|||
# Idea: We can collect all of this information by building part and store it separately in the database
|
||||
# against the uprn. We can have key data for the EPC, but then also additional data for each building
|
||||
# part. We can then use this data to make recommendations that are specific to each building part
|
||||
# We should probably re-think this data model, so we break up the data in a more considered fasion and produce
|
||||
# the underlying EPC data as a summary of the building parts. Not only do we have data against the main
|
||||
# dwelling and extensions, but we also have multiple windows with individiaul pieces of information that
|
||||
# we can use to make recommendations. We should store this data in a way that we can easily access it and
|
||||
# use it to make recommendations (e.g. we should have a Windows table)
|
||||
|
||||
# For each property, we download the xmls and extract the data
|
||||
database_data = []
|
||||
|
|
|
|||
|
|
@ -48,10 +48,14 @@ class WindowsRecommendations:
|
|||
is_secondary_glazing = self.property.restricted_measures or (
|
||||
self.property.windows["glazing_type"] == "secondary"
|
||||
)
|
||||
windows_area = self.property.windows_area
|
||||
|
||||
if not number_of_windows:
|
||||
raise ValueError("Number of windows not specified")
|
||||
|
||||
if windows_area is not None:
|
||||
raise Exception("We have windows area, we should use this data for our recommendations!!!")
|
||||
|
||||
if self.property.windows["has_glazing"] & (
|
||||
self.property.windows["glazing_coverage"] == "full"
|
||||
):
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue