Skip to content

Commit f73bc92

Browse files
authored
Modernize template fan (home-assistant#156470)
1 parent 4506be5 commit f73bc92

File tree

1 file changed

+38
-70
lines changed
  • homeassistant/components/template

1 file changed

+38
-70
lines changed

homeassistant/components/template/fan.py

Lines changed: 38 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -210,17 +210,15 @@ def __init__(self, config: dict[str, Any]) -> None: # pylint: disable=super-ini
210210
self._oscillating_template = config.get(CONF_OSCILLATING)
211211
self._direction_template = config.get(CONF_DIRECTION)
212212

213-
self._state: bool | None = False
214-
self._percentage: int | None = None
215-
self._preset_mode: str | None = None
216-
self._oscillating: bool | None = None
217-
self._direction: str | None = None
213+
# Required for legacy functionality.
214+
self._attr_is_on = False
215+
self._attr_percentage = None
218216

219217
# Number of valid speeds
220-
self._speed_count = config.get(CONF_SPEED_COUNT)
218+
self._attr_speed_count = config.get(CONF_SPEED_COUNT) or 100
221219

222220
# List of valid preset modes
223-
self._preset_modes: list[str] | None = config.get(CONF_PRESET_MODES)
221+
self._attr_preset_modes: list[str] | None = config.get(CONF_PRESET_MODES)
224222

225223
self._attr_supported_features |= (
226224
FanEntityFeature.TURN_OFF | FanEntityFeature.TURN_ON
@@ -240,51 +238,21 @@ def _iterate_scripts(
240238
if (action_config := config.get(action_id)) is not None:
241239
yield (action_id, action_config, supported_feature)
242240

243-
@property
244-
def speed_count(self) -> int:
245-
"""Return the number of speeds the fan supports."""
246-
return self._speed_count or 100
247-
248-
@property
249-
def preset_modes(self) -> list[str] | None:
250-
"""Get the list of available preset modes."""
251-
return self._preset_modes
252-
253241
@property
254242
def is_on(self) -> bool | None:
255243
"""Return true if device is on."""
256-
return self._state
257-
258-
@property
259-
def preset_mode(self) -> str | None:
260-
"""Return the current preset mode."""
261-
return self._preset_mode
262-
263-
@property
264-
def percentage(self) -> int | None:
265-
"""Return the current speed percentage."""
266-
return self._percentage
267-
268-
@property
269-
def oscillating(self) -> bool | None:
270-
"""Return the oscillation state."""
271-
return self._oscillating
272-
273-
@property
274-
def current_direction(self) -> str | None:
275-
"""Return the oscillation state."""
276-
return self._direction
244+
return self._attr_is_on
277245

278246
def _handle_state(self, result) -> None:
279247
if isinstance(result, bool):
280-
self._state = result
248+
self._attr_is_on = result
281249
return
282250

283251
if isinstance(result, str):
284-
self._state = result.lower() in ("true", STATE_ON)
252+
self._attr_is_on = result.lower() in ("true", STATE_ON)
285253
return
286254

287-
self._state = False
255+
self._attr_is_on = False
288256

289257
@callback
290258
def _update_percentage(self, percentage):
@@ -297,69 +265,69 @@ def _update_percentage(self, percentage):
297265
percentage,
298266
self.entity_id,
299267
)
300-
self._percentage = 0
268+
self._attr_percentage = 0
301269
return
302270

303271
if 0 <= percentage <= 100:
304-
self._percentage = percentage
272+
self._attr_percentage = percentage
305273
else:
306274
_LOGGER.error(
307275
"Received invalid percentage: %s for entity %s",
308276
percentage,
309277
self.entity_id,
310278
)
311-
self._percentage = 0
279+
self._attr_percentage = 0
312280

313281
@callback
314282
def _update_preset_mode(self, preset_mode):
315283
# Validate preset mode
316284
preset_mode = str(preset_mode)
317285

318286
if self.preset_modes and preset_mode in self.preset_modes:
319-
self._preset_mode = preset_mode
287+
self._attr_preset_mode = preset_mode
320288
elif preset_mode in (STATE_UNAVAILABLE, STATE_UNKNOWN):
321-
self._preset_mode = None
289+
self._attr_preset_mode = None
322290
else:
323291
_LOGGER.error(
324292
"Received invalid preset_mode: %s for entity %s. Expected: %s",
325293
preset_mode,
326294
self.entity_id,
327295
self.preset_mode,
328296
)
329-
self._preset_mode = None
297+
self._attr_preset_mode = None
330298

331299
@callback
332300
def _update_oscillating(self, oscillating):
333301
# Validate osc
334302
if oscillating == "True" or oscillating is True:
335-
self._oscillating = True
303+
self._attr_oscillating = True
336304
elif oscillating == "False" or oscillating is False:
337-
self._oscillating = False
305+
self._attr_oscillating = False
338306
elif oscillating in (STATE_UNAVAILABLE, STATE_UNKNOWN):
339-
self._oscillating = None
307+
self._attr_oscillating = None
340308
else:
341309
_LOGGER.error(
342310
"Received invalid oscillating: %s for entity %s. Expected: True/False",
343311
oscillating,
344312
self.entity_id,
345313
)
346-
self._oscillating = None
314+
self._attr_oscillating = None
347315

348316
@callback
349317
def _update_direction(self, direction):
350318
# Validate direction
351319
if direction in _VALID_DIRECTIONS:
352-
self._direction = direction
320+
self._attr_current_direction = direction
353321
elif direction in (STATE_UNAVAILABLE, STATE_UNKNOWN):
354-
self._direction = None
322+
self._attr_current_direction = None
355323
else:
356324
_LOGGER.error(
357325
"Received invalid direction: %s for entity %s. Expected: %s",
358326
direction,
359327
self.entity_id,
360328
", ".join(_VALID_DIRECTIONS),
361329
)
362-
self._direction = None
330+
self._attr_current_direction = None
363331

364332
async def async_turn_on(
365333
self,
@@ -383,7 +351,7 @@ async def async_turn_on(
383351
await self.async_set_percentage(percentage)
384352

385353
if self._attr_assumed_state:
386-
self._state = True
354+
self._attr_is_on = True
387355
self.async_write_ha_state()
388356

389357
async def async_turn_off(self, **kwargs: Any) -> None:
@@ -393,46 +361,46 @@ async def async_turn_off(self, **kwargs: Any) -> None:
393361
)
394362

395363
if self._attr_assumed_state:
396-
self._state = False
364+
self._attr_is_on = False
397365
self.async_write_ha_state()
398366

399367
async def async_set_percentage(self, percentage: int) -> None:
400368
"""Set the percentage speed of the fan."""
401-
self._percentage = percentage
369+
self._attr_percentage = percentage
402370

403371
if script := self._action_scripts.get(CONF_SET_PERCENTAGE_ACTION):
404372
await self.async_run_script(
405373
script,
406-
run_variables={ATTR_PERCENTAGE: self._percentage},
374+
run_variables={ATTR_PERCENTAGE: self._attr_percentage},
407375
context=self._context,
408376
)
409377

410378
if self._attr_assumed_state:
411-
self._state = percentage != 0
379+
self._attr_is_on = percentage != 0
412380

413381
if self._attr_assumed_state or self._percentage_template is None:
414382
self.async_write_ha_state()
415383

416384
async def async_set_preset_mode(self, preset_mode: str) -> None:
417385
"""Set the preset_mode of the fan."""
418-
self._preset_mode = preset_mode
386+
self._attr_preset_mode = preset_mode
419387

420388
if script := self._action_scripts.get(CONF_SET_PRESET_MODE_ACTION):
421389
await self.async_run_script(
422390
script,
423-
run_variables={ATTR_PRESET_MODE: self._preset_mode},
391+
run_variables={ATTR_PRESET_MODE: self._attr_preset_mode},
424392
context=self._context,
425393
)
426394

427395
if self._attr_assumed_state:
428-
self._state = True
396+
self._attr_is_on = True
429397

430398
if self._attr_assumed_state or self._preset_mode_template is None:
431399
self.async_write_ha_state()
432400

433401
async def async_oscillate(self, oscillating: bool) -> None:
434402
"""Set oscillation of the fan."""
435-
self._oscillating = oscillating
403+
self._attr_oscillating = oscillating
436404
if (
437405
script := self._action_scripts.get(CONF_SET_OSCILLATING_ACTION)
438406
) is not None:
@@ -448,7 +416,7 @@ async def async_oscillate(self, oscillating: bool) -> None:
448416
async def async_set_direction(self, direction: str) -> None:
449417
"""Set the direction of the fan."""
450418
if direction in _VALID_DIRECTIONS:
451-
self._direction = direction
419+
self._attr_current_direction = direction
452420
if (
453421
script := self._action_scripts.get(CONF_SET_DIRECTION_ACTION)
454422
) is not None:
@@ -496,7 +464,7 @@ def __init__(
496464
def _update_state(self, result):
497465
super()._update_state(result)
498466
if isinstance(result, TemplateError):
499-
self._state = None
467+
self._attr_is_on = None
500468
return
501469

502470
self._handle_state(result)
@@ -506,36 +474,36 @@ def _async_setup_templates(self) -> None:
506474
"""Set up templates."""
507475
if self._template:
508476
self.add_template_attribute(
509-
"_state", self._template, None, self._update_state
477+
"_attr_is_on", self._template, None, self._update_state
510478
)
511479

512480
if self._preset_mode_template is not None:
513481
self.add_template_attribute(
514-
"_preset_mode",
482+
"_attr_preset_mode",
515483
self._preset_mode_template,
516484
None,
517485
self._update_preset_mode,
518486
none_on_template_error=True,
519487
)
520488
if self._percentage_template is not None:
521489
self.add_template_attribute(
522-
"_percentage",
490+
"_attr_percentage",
523491
self._percentage_template,
524492
None,
525493
self._update_percentage,
526494
none_on_template_error=True,
527495
)
528496
if self._oscillating_template is not None:
529497
self.add_template_attribute(
530-
"_oscillating",
498+
"_attr_oscillating",
531499
self._oscillating_template,
532500
None,
533501
self._update_oscillating,
534502
none_on_template_error=True,
535503
)
536504
if self._direction_template is not None:
537505
self.add_template_attribute(
538-
"_direction",
506+
"_attr_current_direction",
539507
self._direction_template,
540508
None,
541509
self._update_direction,

0 commit comments

Comments
 (0)