Implemeted solar api wip

This commit is contained in:
Khalim Conn-Kowlessar 2024-07-11 19:22:10 +01:00
parent b20e00a736
commit 1d28a7e335
10 changed files with 62 additions and 17 deletions

View file

@ -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 = {}

View file

@ -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 = {}

View file

@ -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"}

View file

@ -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)

View file

@ -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"
}
}
)

View file

@ -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"]

View file

@ -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
}
]

View file

@ -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

View file

@ -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},
}
)

View file

@ -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",
}
}
]