mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-06-08 11:17:27 +00:00
Implemeted solar api wip
This commit is contained in:
parent
b20e00a736
commit
1d28a7e335
10 changed files with 62 additions and 17 deletions
|
|
@ -351,6 +351,7 @@ class Property:
|
|||
if r["phase"] <= phase
|
||||
]
|
||||
epc_transformations = [x["description_simulation"] for x in represenative_recs_to_this_phase]
|
||||
|
||||
# It is possible that we could have two simulations applied to the same descriptions
|
||||
# We extract these out
|
||||
phase_epc_transformation = {}
|
||||
|
|
|
|||
|
|
@ -448,12 +448,13 @@ async def trigger_plan(body: PlanTriggerRequest):
|
|||
p.set_solar_panel_configuration(unit_solar_panel_configuration)
|
||||
|
||||
else:
|
||||
# Model the solar potential at the property level
|
||||
for p in input_properties:
|
||||
# TODO: Complete me! - we probably won't do this for individual flats
|
||||
solar_performance = solar_api_client.get(
|
||||
longitude=p.spatial["longitude"], latitude=p.spatial["latitude"]
|
||||
)
|
||||
# # Model the solar potential at the property level
|
||||
# for p in input_properties:
|
||||
# # TODO: Complete me! - we probably won't do this for individual flats
|
||||
# solar_performance = solar_api_client.get(
|
||||
# longitude=p.spatial["longitude"], latitude=p.spatial["latitude"]
|
||||
# )
|
||||
print("Implement me")
|
||||
|
||||
logger.info("Getting components and epc recommendations")
|
||||
recommendations = {}
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ class PlanTriggerRequest(BaseModel):
|
|||
|
||||
# Pre-defined list of possibilities for exclusions
|
||||
_allowed_exclusions = {
|
||||
# Measure classes
|
||||
"wall_insulation",
|
||||
"ventilation",
|
||||
"roof_insulation",
|
||||
|
|
@ -25,7 +26,9 @@ class PlanTriggerRequest(BaseModel):
|
|||
"heating",
|
||||
"hot_water",
|
||||
"lighting",
|
||||
"solar_pv"
|
||||
"solar_pv",
|
||||
# Specific measures
|
||||
"air_source_heat_pump",
|
||||
}
|
||||
|
||||
_allowed_goals = {"Increase EPC"}
|
||||
|
|
|
|||
|
|
@ -119,11 +119,12 @@ def app():
|
|||
"portfolio_id": str(PORTFOLIO_ID),
|
||||
"housing_type": "Private",
|
||||
"goal": "Increase EPC",
|
||||
"goal_value": "A",
|
||||
"goal_value": "C",
|
||||
"trigger_file_path": filename,
|
||||
"already_installed_file_path": already_installed_filename,
|
||||
"patches_file_path": "",
|
||||
"non_invasive_recommendations_file_path": "",
|
||||
"exclusions": ["wall_insulation", "air_source_heat_pump"],
|
||||
"budget": None,
|
||||
}
|
||||
print(body)
|
||||
|
|
|
|||
|
|
@ -190,7 +190,11 @@ class HeatingControlRecommender:
|
|||
"new_u_value": None,
|
||||
"sap_points": None,
|
||||
"already_installed": already_installed,
|
||||
"simulation_config": simulation_config
|
||||
"simulation_config": simulation_config,
|
||||
"description_simulation": {
|
||||
"mainheatcont-description": "Programmer, room thermostat and TRVS",
|
||||
"mainheatc-energy-eff": "Good"
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
|
|
@ -250,6 +254,10 @@ class HeatingControlRecommender:
|
|||
"new_u_value": None,
|
||||
"sap_points": None,
|
||||
"already_installed": already_installed,
|
||||
"simulation_config": simulation_config
|
||||
"simulation_config": simulation_config,
|
||||
"description_simulation": {
|
||||
"mainheatcont-description": "Time and temperature zone control",
|
||||
"mainheatc-energy-eff": "Very Good"
|
||||
}
|
||||
}
|
||||
)
|
||||
|
|
|
|||
|
|
@ -42,18 +42,21 @@ class HeatingRecommender:
|
|||
|
||||
return self.has_electric_heating_description or electric_heating_assumed
|
||||
|
||||
def recommend(self, has_cavity_or_loft_recommendations, phase=0):
|
||||
def recommend(self, has_cavity_or_loft_recommendations, phase=0, exclusions=None):
|
||||
"""
|
||||
Produces heating recommendations
|
||||
:param has_cavity_or_loft_recommendations: boolean indicating if we have produced a cavity or loft insulation
|
||||
recommendation. If there are cavity or loft recommendations, the property would need to complete those measures
|
||||
before being able to get the boiler upgrade scheme benefits. The messaging in the front end would be to
|
||||
:param phase: indicates the phase of the retrofit programme
|
||||
:param exclusions: A list of exclusions for the recommendations
|
||||
"""
|
||||
|
||||
# TODO: We could have a system flush recommendation for an existing boiler, where there is no need to replace
|
||||
# the boiler, but instead flushing the system will make it run more efficiently. There is a cost for this
|
||||
# in the Costs class, stored as SYSTEM_FLUSH_COST
|
||||
|
||||
exclusions = [] if exclusions is None else exclusions
|
||||
|
||||
self.heating_recommendations = []
|
||||
self.heating_control_recommendations = []
|
||||
|
|
@ -112,7 +115,7 @@ class HeatingRecommender:
|
|||
# In the future, we'll allow overrides, so that non-intrusive surveys can contradict these conditions
|
||||
# and either allow or prevent the recommendation of an air source heat pump
|
||||
|
||||
if self.is_ashp_valid():
|
||||
if self.is_ashp_valid(exclusions=exclusions):
|
||||
self.recommend_air_source_heat_pump(
|
||||
phase=phase, has_cavity_or_loft_recommendations=has_cavity_or_loft_recommendations
|
||||
)
|
||||
|
|
@ -182,11 +185,14 @@ class HeatingRecommender:
|
|||
description = ("Replace the existing boiler and cylinder without a thermostat with a new electric combi "
|
||||
"boiler")
|
||||
|
||||
def is_ashp_valid(self):
|
||||
def is_ashp_valid(self, exclusions):
|
||||
|
||||
if "air_source_heat_pump" in self.property.non_invasive_recommendations:
|
||||
return True
|
||||
|
||||
if "air_source_heat_pump" in exclusions:
|
||||
return False
|
||||
|
||||
suitable_property_type = self.property.data["property-type"] in ["House", "Bungalow"]
|
||||
has_air_source_heat_pump = self.property.main_heating["has_air_source_heat_pump"]
|
||||
|
||||
|
|
|
|||
|
|
@ -109,8 +109,12 @@ class LightingRecommendations:
|
|||
# For SAP points, we use the fact that lighting is usually worth 2 points and we scale this to
|
||||
# the proportion of lights that will be set to low energy
|
||||
"sap_points": round(2 * (number_non_lel_outlets / number_lighting_outlets), 2),
|
||||
"heat_demand": heat_demand_change,
|
||||
"kwh_savings": heat_demand_change,
|
||||
"co2_equivalent_savings": carbon_change,
|
||||
"description_simulation": {
|
||||
"lighting-energy-eff": "Very Good",
|
||||
"lighting-description": "Low energy lighting in all fixed outlets",
|
||||
},
|
||||
**cost_result
|
||||
}
|
||||
]
|
||||
|
|
|
|||
|
|
@ -119,7 +119,9 @@ class Recommendations:
|
|||
has_cavity_or_loft_recommendations = len(cavity_or_loft_recommendations) > 0
|
||||
|
||||
self.heating_recommender.recommend(
|
||||
phase=phase, has_cavity_or_loft_recommendations=has_cavity_or_loft_recommendations
|
||||
phase=phase,
|
||||
has_cavity_or_loft_recommendations=has_cavity_or_loft_recommendations,
|
||||
exclusions=self.exclusions
|
||||
)
|
||||
if (
|
||||
self.heating_recommender.heating_recommendations or
|
||||
|
|
@ -294,6 +296,13 @@ class Recommendations:
|
|||
if rec["type"] != "solar_pv":
|
||||
return 0, 0
|
||||
|
||||
if property_instance.solar_panel_configuration is None:
|
||||
print("PLACEHOLDER ESTIMATES")
|
||||
# 50% reduction average
|
||||
kwh_reduction = property_instance.energy_consumption_estimates["adjusted"]["appliances"] * 0.5
|
||||
predicted_appliances_cost_reduction = kwh_reduction * AnnualBillSavings.ELECTRICITY_PRICE_CAP
|
||||
return predicted_appliances_cost_reduction, kwh_reduction
|
||||
|
||||
# Calulate the amount of energy the solar panel array will generate for this unit
|
||||
unit_energy_consumption = (
|
||||
rec["initial_ac_kwh_per_year"] *
|
||||
|
|
@ -721,10 +730,14 @@ class Recommendations:
|
|||
heating_kwh_reduction = 0 if predicted_heating_cost_reduction == 0 else (
|
||||
phase_kwh_figures[previous_phase]["adjusted"]["heating"] - new_heating_kwh_adjusted
|
||||
)
|
||||
if heating_kwh_reduction < 0:
|
||||
heating_kwh_reduction = 0
|
||||
|
||||
hot_water_kwh_reduction = 0 if predicted_hot_water_cost_reduction == 0 else (
|
||||
phase_kwh_figures[previous_phase]["adjusted"]["hot_water"] - new_hot_water_kwh_adjusted
|
||||
)
|
||||
if hot_water_kwh_reduction < 0:
|
||||
hot_water_kwh_reduction = 0
|
||||
|
||||
lighting_kwh_reduction = predicted_lighting_cost_reduction / AnnualBillSavings.ELECTRICITY_PRICE_CAP
|
||||
|
||||
|
|
@ -773,7 +786,7 @@ class Recommendations:
|
|||
# For the moment, we cap the number of SAP points that can be achieved by ventilation at 2
|
||||
rec["sap_points"] = min(predicted_sap_points, LightingRecommendations.SAP_LIMIT)
|
||||
rec["co2_equivalent_savings"] = min(predicted_co2_savings, rec["co2_equivalent_savings"])
|
||||
rec["heat_demand"] = min(predicted_heat_demand, rec["heat_demand"])
|
||||
rec["heat_demand"] = predicted_heat_demand
|
||||
else:
|
||||
rec["sap_points"] = predicted_sap_points
|
||||
rec["co2_equivalent_savings"] = predicted_co2_savings
|
||||
|
|
|
|||
|
|
@ -244,6 +244,7 @@ class SolarPvRecommendations:
|
|||
# This is required for simulating the SAP impact. solar_pv_percentage is between 0 & 1 so we scale
|
||||
# back up here
|
||||
"photo_supply": 100 * roof_coverage,
|
||||
"has_battery": has_battery
|
||||
"has_battery": has_battery,
|
||||
"description_simulation": {"photo-supply": 100 * roof_coverage},
|
||||
}
|
||||
)
|
||||
|
|
|
|||
|
|
@ -115,5 +115,12 @@ class WindowsRecommendations:
|
|||
"already_installed": already_installed,
|
||||
**cost_result,
|
||||
"is_secondary_glazing": is_secondary_glazing,
|
||||
# TODO: Make this condition on is_secondary_glazing
|
||||
"description_simulation": {
|
||||
"multi-glaze-proportion": 100,
|
||||
"windows-energy-eff": "Average",
|
||||
"windows-description": "Fully double glazed",
|
||||
"glazed-type": "double glazing installed during or after 2002",
|
||||
}
|
||||
}
|
||||
]
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue