Model/recommendations/HeatingControlRecommender.py
2024-04-11 16:49:44 +01:00

228 lines
10 KiB
Python

from recommendations.Costs import Costs
from recommendations.recommendation_utils import check_simulation_difference
from backend.Property import Property
from etl.epc_clean.epc_attributes.MainheatControlAttributes import MainheatControlAttributes
class HeatingControlRecommender:
def __init__(self, property_instance: Property):
self.property = property_instance
self.costs = Costs(self.property)
self.recommendation = []
def recommend(self, heating_description):
# Reset the recommendations
self.recommendation = []
# This first iteration of the recommender will provide very basic recommendation
# We recommend heating controls based on the main heating system
if heating_description in ["Room heaters, electric"]:
self.recommend_room_heaters_electric_controls()
return
if heating_description in ["Electric storage heaters", "Electric storage heaters, radiators"]:
self.recommend_high_heat_retention_controls()
return
if heating_description in ["Boiler and radiators, mains gas"]:
# We can recommend roomstat programmer trvs
self.recommend_roomstat_programmer_trvs()
# We can also recommend time and temperature zone controls
self.recommend_time_temperature_zone_controls()
return
def recommend_room_heaters_electric_controls(self):
"""
If the home has Room heaters, electric, we start by identifying potential heating controls that could
be upgraded, that would provide a practical impact. This will be the least invasive improvement.
We can then consider the heating system itself
:return:
"""
if (self.property.data["mainheatc-energy-eff"] in ["Poor", "Very Poor", "Average"]) or (
self.property.main_heating_controls["clean_description"] in ["Programmer and room thermostat"]
):
# We recommend Programmer and appliance thermostats as the heating control. This has an average energy
# efficiency rating, and is likely to be more efficient than the current heating controls. if the
# rating is poor or very poor, the home may have a Programmer and room thermostat, which is less efficient
# than a Programmer and appliance thermostats, because it allows for much more granular control at not
# just a room level but individual heater/appliance level
# Note: A room thermostat is commonly placed in a hallway, and it measures the temperature of the air
# surrounding it. It then sends a signal to the heating system to turn on or off, depending on the
# temperature. An appliance thermostat, on the other hand, is placed on the heater/appliance itself, and
# measures the temperature of the heater/appliance. This allows for much more granular control, and
# prevents overheating.
# In order to cost, we check if the property already has a programmer, and therefor we will just need to
# add the cost of the appliance thermostats
has_programmer = self.property.main_heating_controls["switch_system"] == "programmer"
ending_config = MainheatControlAttributes("Programmer and appliance thermostats").process()
# We look at what has changed in the ending config, and compare it to the current config
# We use this to determine how we should be updating the config
simulation_config = check_simulation_difference(
new_config=ending_config, old_config=self.property.main_heating_controls
)
# This upgrade will only take the heating system to average energy efficiency
simulation_config["mainheatc_energy_eff_ending"] = "Good"
self.recommendation.append(
{
"description": "upgrade heating controls to Programmer and Appliance or Smart Thermostats",
**self.costs.programmer_and_appliance_thermostat(has_programmer=has_programmer),
"simulation_config": simulation_config
}
)
# We don't implement any other recommendations right now
return
def recommend_high_heat_retention_controls(self):
"""
When applicable, we recommend upgrading the heating controls to high heat retention controls. This is a
specific type of control system that is designed to work with electric storage heaters. It is a more
efficient control system than the standard controls that come with electric storage heaters.
We can then consider the heating system itself
:return:
"""
# We recommend upgrading to Celect type controls
ending_config = MainheatControlAttributes("Controls for high heat retention storage heaters").process()
# We look at what has changed in the ending config, and compare it to the current config
simulation_config = check_simulation_difference(
new_config=ending_config, old_config=self.property.main_heating_controls
)
# This upgrade will only take the heating system to average energy efficiency
simulation_config["mainheatc_energy_eff_ending"] = "Good"
self.recommendation.append(
{
"description": "upgrade heating controls to High Heat Retention Storage Heater Controls",
**self.costs.celect_type_controls(),
"simulation_config": simulation_config
}
)
# We don't implement any other recommendations right now
return
def recommend_roomstat_programmer_trvs(self):
"""
If the home has a boiler and radiators, mains gas, we start by identifying potential heating controls that could
be upgraded, that would provide a practical impact.
The criteria for recommending an upgrade to heating controls are (one of these must be true)
1) There are no controls
2) No programmer
3) No room thermostat
4) No TRVs
:return:
"""
# We check if we have the conditions to recommend this upgrade
needs_programmer = self.property.main_heating_controls["switch_system"] is None
needs_room_thermostat = self.property.main_heating_controls["thermostatic_control"] is None
needs_trvs = self.property.main_heating_controls["trvs"] is None
can_recommend = (
(self.property.main_heating_controls["no_control"] is not None) or
needs_programmer or
needs_room_thermostat or
needs_trvs
)
if not can_recommend:
return
ending_config = MainheatControlAttributes("Programmer, room thermostat and TRVS").process()
# We use this to determine how we should be updating the config
simulation_config = check_simulation_difference(
new_config=ending_config, old_config=self.property.main_heating_controls
)
# This upgrade will only take the heating system to average energy efficiency
# If the current system is below good, we make it good
if self.property.data["mainheatc-energy-eff"] in ["Poor", "Very Poor", "Average"]:
simulation_config["mainheatc_energy_eff_ending"] = "Good"
has_programmer = not needs_programmer
has_room_thermostat = not needs_room_thermostat
has_trvs = not needs_trvs
self.recommendation.append(
{
"type": "heating_control",
"parts": [],
"description": "upgrade heating controls to Room thermostat, programmer and TRVs",
**self.costs.roomstat_programmer_trvs(
number_heated_rooms=int(self.property.data["number-heated-rooms"]),
has_programmer=has_programmer,
has_room_thermostat=has_room_thermostat,
has_trvs=has_trvs
),
"starting_u_value": None,
"new_u_value": None,
"sap_points": None,
"simulation_config": simulation_config
}
)
return
def recommend_time_temperature_zone_controls(self):
"""
If the home has a boiler, we can recommend time and temperature zone controls. This is a more advanced
and more efficient control system than the standard controls that come with a boiler. However, it may come
with a higher cost and more involved usage
:return:
"""
# We check if the efficiency of the current heating controls is good or below, and
# Conditions for installation are as follows:
# 1) The current heating controls are not time and temperature zone controls
# 2) The current heating controls are not already at 'Very Good' or above
if (
(self.property.main_heating_controls["thermostatic_control"] == "time and temperature zone control") or
(self.property.data["mainheatc-energy-eff"] in ["Very Good"])
):
# No recommendation needed
return
ending_config = MainheatControlAttributes("Time and temperature zone control").process()
# We use this to determine how we should be updating the config
simulation_config = check_simulation_difference(
new_config=ending_config, old_config=self.property.main_heating_controls
)
# If the current system is below very good, we make it very good
if self.property.data["mainheatc-energy-eff"] in ["Poor", "Very Poor", "Average", "Good"]:
simulation_config["mainheatc_energy_eff_ending"] = "Very Good"
self.recommendation.append(
{
"type": "heating_control",
"parts": [],
"description": "Upgrade heating controls to Smart Thermostats, room sensors and smart radiator valves "
"(time & temperature zone control)",
**self.costs.time_and_temperature_zone_control(
number_heated_rooms=int(self.property.data["number-heated-rooms"])
),
"starting_u_value": None,
"new_u_value": None,
"sap_points": None,
"simulation_config": simulation_config
}
)