Skip to content

Commit 7f63503

Browse files
author
Jean-Marc Collin
committed
Issue #223 - add auto_fan_mode
1 parent f7c4e20 commit 7f63503

File tree

16 files changed

+763
-114
lines changed

16 files changed

+763
-114
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,3 +109,4 @@ __pycache__
109109

110110
config/**
111111
custom_components/hacs
112+
custom_components/localtuya

custom_components/versatile_thermostat/base_thermostat.py

Lines changed: 18 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,6 @@
102102
CONF_TEMP_MIN,
103103
HIDDEN_PRESETS,
104104
CONF_AC_MODE,
105-
UnknownEntity,
106105
EventType,
107106
ATTR_MEAN_POWER_CYCLE,
108107
ATTR_TOTAL_ENERGY,
@@ -259,6 +258,8 @@ def __init__(self, hass: HomeAssistant, unique_id, name, entry_infos) -> None:
259258
self._ema_temp = None
260259
self._ema_algo = None
261260
self._now = None
261+
262+
self._attr_fan_mode = None
262263
self.post_init(entry_infos)
263264

264265
def post_init(self, entry_infos):
@@ -555,11 +556,7 @@ async def async_added_to_hass(self):
555556

556557
self.async_on_remove(self.remove_thermostat)
557558

558-
try:
559-
await self.async_startup()
560-
except UnknownEntity:
561-
# Ingore this error which is possible if underlying climate is not found temporary
562-
pass
559+
await self.async_startup()
563560

564561
def remove_thermostat(self):
565562
"""Called when the thermostat will be removed"""
@@ -577,12 +574,7 @@ async def _async_startup_internal(*_):
577574
need_write_state = False
578575

579576
# Initialize all UnderlyingEntities
580-
for under in self._underlyings:
581-
try:
582-
under.startup()
583-
except UnknownEntity:
584-
# Not found, we will try later
585-
pass
577+
self.init_underlyings()
586578

587579
temperature_state = self.hass.states.get(self._temp_sensor_entity_id)
588580
if temperature_state and temperature_state.state not in (
@@ -723,6 +715,9 @@ async def _async_startup_internal(*_):
723715
EVENT_HOMEASSISTANT_START, _async_startup_internal
724716
)
725717

718+
def init_underlyings(self):
719+
"""Initialize all underlyings. Should be overriden if necessary"""
720+
726721
def restore_specific_previous_state(self, old_state):
727722
"""Should be overriden in each specific thermostat
728723
if a specific previous state or attribute should be
@@ -2089,6 +2084,13 @@ async def check_security(self) -> bool:
20892084

20902085
return shouldBeInSecurity
20912086

2087+
@property
2088+
def is_initialized(self) -> bool:
2089+
"""Check if all underlyings are initialized
2090+
This is usefull only for over_climate in which we
2091+
should have found the underlying climate to be operational"""
2092+
return True
2093+
20922094
async def async_control_heating(self, force=False, _=None):
20932095
"""The main function used to run the calculation at each cycle"""
20942096

@@ -2104,18 +2106,10 @@ async def async_control_heating(self, force=False, _=None):
21042106
await self._async_manage_window_auto(in_cycle=True)
21052107

21062108
# Issue 56 in over_climate mode, if the underlying climate is not initialized, try to initialize it
2107-
for under in self._underlyings:
2108-
if not under.is_initialized:
2109-
_LOGGER.info(
2110-
"%s - Underlying %s is not initialized. Try to initialize it",
2111-
self,
2112-
under.entity_id,
2113-
)
2114-
try:
2115-
under.startup()
2116-
except UnknownEntity:
2117-
# still not found, we an stop here
2118-
return False
2109+
if not self.is_initialized:
2110+
if not self.init_underlyings():
2111+
# still not found, we an stop here
2112+
return False
21192113

21202114
# Check overpowering condition
21212115
# Not necessary for switch because each switch is checking at startup

custom_components/versatile_thermostat/climate.py

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,13 @@
1515

1616
from homeassistant.helpers import entity_platform
1717

18-
from homeassistant.const import CONF_NAME, STATE_ON, STATE_OFF, STATE_HOME, STATE_NOT_HOME
18+
from homeassistant.const import (
19+
CONF_NAME,
20+
STATE_ON,
21+
STATE_OFF,
22+
STATE_HOME,
23+
STATE_NOT_HOME,
24+
)
1925

2026
from .const import (
2127
DOMAIN,
@@ -26,10 +32,11 @@
2632
SERVICE_SET_SECURITY,
2733
SERVICE_SET_WINDOW_BYPASS,
2834
SERVICE_SET_AUTO_REGULATION_MODE,
35+
SERVICE_SET_AUTO_FAN_MODE,
2936
CONF_THERMOSTAT_TYPE,
3037
CONF_THERMOSTAT_SWITCH,
3138
CONF_THERMOSTAT_CLIMATE,
32-
CONF_THERMOSTAT_VALVE
39+
CONF_THERMOSTAT_VALVE,
3340
)
3441

3542
from .thermostat_switch import ThermostatOverSwitch
@@ -102,16 +109,27 @@ async def async_setup_entry(
102109
platform.async_register_entity_service(
103110
SERVICE_SET_WINDOW_BYPASS,
104111
{
105-
vol.Required("window_bypass"): vol.In([True, False]
106-
),
112+
vol.Required("window_bypass"): vol.In([True, False]),
107113
},
108114
"service_set_window_bypass_state",
109115
)
110116

111117
platform.async_register_entity_service(
112118
SERVICE_SET_AUTO_REGULATION_MODE,
113119
{
114-
vol.Required("auto_regulation_mode"): vol.In(["None", "Light", "Medium", "Strong", "Slow"]),
120+
vol.Required("auto_regulation_mode"): vol.In(
121+
["None", "Light", "Medium", "Strong", "Slow"]
122+
),
115123
},
116124
"service_set_auto_regulation_mode",
117125
)
126+
127+
platform.async_register_entity_service(
128+
SERVICE_SET_AUTO_FAN_MODE,
129+
{
130+
vol.Required("auto_fan_mode"): vol.In(
131+
["None", "Low", "Medium", "High", "Turbo"]
132+
),
133+
},
134+
"service_set_auto_fan_mode",
135+
)

custom_components/versatile_thermostat/config_flow.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,9 @@
107107
CONF_INVERSE_SWITCH,
108108
UnknownEntity,
109109
WindowOpenDetectionMethod,
110+
CONF_AUTO_FAN_MODES,
111+
CONF_AUTO_FAN_MODE,
112+
CONF_AUTO_FAN_HIGH,
110113
)
111114

112115
_LOGGER = logging.getLogger(__name__)
@@ -275,6 +278,14 @@ def __init__(self, infos) -> None:
275278
vol.Optional(
276279
CONF_AUTO_REGULATION_PERIOD_MIN, default=5
277280
): cv.positive_int,
281+
vol.Optional(
282+
CONF_AUTO_FAN_MODE, default=CONF_AUTO_FAN_HIGH
283+
): selector.SelectSelector(
284+
selector.SelectSelectorConfig(
285+
options=CONF_AUTO_FAN_MODES,
286+
translation_key="auto_fan_mode",
287+
)
288+
),
278289
}
279290
)
280291

custom_components/versatile_thermostat/const.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,12 @@
9595
CONF_AUTO_REGULATION_PERIOD_MIN = "auto_regulation_periode_min"
9696
CONF_INVERSE_SWITCH = "inverse_switch_command"
9797
CONF_SHORT_EMA_PARAMS = "short_ema_params"
98+
CONF_AUTO_FAN_MODE = "auto_fan_mode"
99+
CONF_AUTO_FAN_NONE = "auto_fan_none"
100+
CONF_AUTO_FAN_LOW = "auto_fan_low"
101+
CONF_AUTO_FAN_MEDIUM = "auto_fan_medium"
102+
CONF_AUTO_FAN_HIGH = "auto_fan_high"
103+
CONF_AUTO_FAN_TURBO = "auto_fan_turbo"
98104

99105
DEFAULT_SHORT_EMA_PARAMS = {
100106
"max_alpha": 0.5,
@@ -233,20 +239,32 @@
233239
CONF_THERMOSTAT_VALVE,
234240
]
235241

242+
CONF_AUTO_FAN_MODES = [
243+
CONF_AUTO_FAN_NONE,
244+
CONF_AUTO_FAN_LOW,
245+
CONF_AUTO_FAN_MEDIUM,
246+
CONF_AUTO_FAN_HIGH,
247+
CONF_AUTO_FAN_TURBO,
248+
]
249+
236250
SUPPORT_FLAGS = ClimateEntityFeature.TARGET_TEMPERATURE
237251

238252
SERVICE_SET_PRESENCE = "set_presence"
239253
SERVICE_SET_PRESET_TEMPERATURE = "set_preset_temperature"
240254
SERVICE_SET_SECURITY = "set_security"
241255
SERVICE_SET_WINDOW_BYPASS = "set_window_bypass"
242256
SERVICE_SET_AUTO_REGULATION_MODE = "set_auto_regulation_mode"
257+
SERVICE_SET_AUTO_FAN_MODE = "set_auto_fan_mode"
243258

244259
DEFAULT_SECURITY_MIN_ON_PERCENT = 0.5
245260
DEFAULT_SECURITY_DEFAULT_ON_PERCENT = 0.1
246261

247262
ATTR_TOTAL_ENERGY = "total_energy"
248263
ATTR_MEAN_POWER_CYCLE = "mean_cycle_power"
249264

265+
AUTO_FAN_DTEMP_THRESHOLD = 2
266+
AUTO_FAN_DEACTIVATED_MODES = ["mute", "silent", "auto", "low"]
267+
250268

251269
# A special regulation parameter suggested by @Maia here: https://github.com/jmcollin78/versatile_thermostat/discussions/154
252270
class RegulationParamSlow:

custom_components/versatile_thermostat/services.yaml

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,3 +161,25 @@ set_auto_regulation_mode:
161161
- "Strong"
162162
- "Slow"
163163
- "Expert"
164+
165+
set_auto_fan_mode:
166+
name: Set Auto Fan mode
167+
description: Change the mode of auto-fan (only for VTherm over climate)
168+
target:
169+
entity:
170+
integration: versatile_thermostat
171+
fields:
172+
auto_fan_mode:
173+
name: Auto fan mode
174+
description: Possible values
175+
required: true
176+
advanced: false
177+
default: true
178+
selector:
179+
select:
180+
options:
181+
- "None"
182+
- "Low"
183+
- "Medium"
184+
- "High"
185+
- "Turbo"

0 commit comments

Comments
 (0)