-
Notifications
You must be signed in to change notification settings - Fork 76
Fix thermostat fan modes to respect fanModeSequence #708
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: dev
Are you sure you want to change the base?
Changes from 20 commits
d25a53f
2886d25
2304728
75510aa
dad0f4d
edfb246
cb6aa3b
4e3737c
4f3b43b
08c3a7a
2dcb767
29b4b0d
4b4a111
dcee206
a83fa04
b3752d5
f4ca46c
02195a6
e636bb3
cb51c85
4db4310
666c011
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -19,7 +19,6 @@ | |
| ) | ||
| from zigpy.zcl.clusters.hvac import ( | ||
| Fan as FanCluster, | ||
| FanMode, | ||
| RunningState, | ||
| SystemMode, | ||
| Thermostat as ThermostatCluster, | ||
|
|
@@ -40,18 +39,22 @@ | |
| ATTR_OCCP_COOL_SETPT, | ||
| ATTR_OCCP_HEAT_SETPT, | ||
| FAN_AUTO, | ||
| FAN_MODE_TO_ZCL, | ||
| FAN_ON, | ||
| HVAC_MODE_2_SYSTEM, | ||
| PRECISION_TENTHS, | ||
| SEQ_FAN_MODES, | ||
| SEQ_OF_OPERATION, | ||
| SYSTEM_MODE_2_HVAC, | ||
| ZCL_TEMP, | ||
| ZCL_TO_FAN_MODE, | ||
| ClimateEntityFeature, | ||
| HVACAction, | ||
| HVACMode, | ||
| Preset, | ||
| ) | ||
| from zha.decorators import periodic | ||
| from zha.quirks import THERMOSTAT_FAN_ONLY_HVAC | ||
| from zha.units import UnitOfTemperature | ||
|
|
||
| if TYPE_CHECKING: | ||
|
|
@@ -598,6 +601,11 @@ def outdoor_temperature(self): | |
| @property | ||
| def fan_mode(self) -> str | None: | ||
| """Return current FAN mode.""" | ||
| if self._fan_cluster is not None: | ||
| current = self._fan_cluster.get(FanCluster.AttributeDefs.fan_mode.name) | ||
|
vmvarga marked this conversation as resolved.
|
||
| if current is not None: | ||
| return ZCL_TO_FAN_MODE.get(current, FAN_AUTO) | ||
|
vmvarga marked this conversation as resolved.
Outdated
|
||
|
|
||
| running_state = self._running_state | ||
| if running_state is None: | ||
| return FAN_AUTO | ||
|
|
@@ -610,12 +618,13 @@ def fan_mode(self) -> str | None: | |
| return FAN_ON | ||
| return FAN_AUTO | ||
|
|
||
| @functools.cached_property | ||
| @property | ||
| def fan_modes(self) -> list[str] | None: | ||
| """Return supported FAN modes.""" | ||
| if self._fan_cluster is None: | ||
| return None | ||
| return [FAN_AUTO, FAN_ON] | ||
| seq = self._fan_cluster.get(FanCluster.AttributeDefs.fan_mode_sequence.name) | ||
| return SEQ_FAN_MODES.get(seq, [FAN_ON, FAN_AUTO]) | ||
|
vmvarga marked this conversation as resolved.
Outdated
|
||
|
|
||
| @property | ||
| def hvac_action(self) -> HVACAction | None: | ||
|
|
@@ -673,7 +682,14 @@ def hvac_mode(self) -> HVACMode | None: | |
| @property | ||
| def hvac_modes(self) -> list[HVACMode]: | ||
| """Return the list of available HVAC operation modes.""" | ||
| return SEQ_OF_OPERATION.get(self._ctrl_sequence_of_oper, [HVACMode.OFF]) | ||
| modes = SEQ_OF_OPERATION.get(self._ctrl_sequence_of_oper, [HVACMode.OFF]) | ||
| if ( | ||
| self._fan_cluster is not None | ||
| and THERMOSTAT_FAN_ONLY_HVAC in self._device.exposes_features | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not saying we should, but if we wanted to, we could also have another entity class that overrides the fist one (so likely using a feature group) and then matches on the exposed feature. There, we'd only add |
||
| and HVACMode.FAN_ONLY not in modes | ||
| ): | ||
| modes = [*modes, HVACMode.FAN_ONLY] | ||
| return modes | ||
|
|
||
| @property | ||
| def preset_mode(self) -> str: | ||
|
|
@@ -804,10 +820,13 @@ async def async_set_fan_mode(self, fan_mode: str) -> None: | |
| self.warning("Unsupported '%s' fan mode", fan_mode) | ||
| return | ||
|
|
||
| mode = FanMode.On if fan_mode == FAN_ON else FanMode.Auto | ||
| zcl_mode = FAN_MODE_TO_ZCL.get(fan_mode) | ||
| if zcl_mode is None: | ||
| self.warning("No ZCL mapping for fan mode '%s'", fan_mode) | ||
| return | ||
|
|
||
| await write_attributes_safe( | ||
| self._fan_cluster, {FanCluster.AttributeDefs.fan_mode.name: mode} | ||
| self._fan_cluster, {FanCluster.AttributeDefs.fan_mode.name: zcl_mode} | ||
| ) | ||
|
|
||
| async def async_set_hvac_mode(self, hvac_mode: HVACMode) -> None: | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.