Skip to content

Commit 0b2bb9f

Browse files
authored
Modernize template binary sensor (home-assistant#157279)
1 parent 0769163 commit 0b2bb9f

File tree

1 file changed

+35
-20
lines changed

1 file changed

+35
-20
lines changed

homeassistant/components/template/binary_sensor.py

Lines changed: 35 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
from homeassistant.util import dt as dt_util
4949

5050
from . import TriggerUpdateCoordinator
51+
from .entity import AbstractTemplateEntity
5152
from .helpers import (
5253
async_setup_template_entry,
5354
async_setup_template_platform,
@@ -168,11 +169,27 @@ def async_create_preview_binary_sensor(
168169
)
169170

170171

171-
class StateBinarySensorEntity(TemplateEntity, BinarySensorEntity, RestoreEntity):
172+
class AbstractTemplateBinarySensor(
173+
AbstractTemplateEntity, BinarySensorEntity, RestoreEntity
174+
):
175+
"""Representation of a template binary sensor features."""
176+
177+
_entity_id_format = ENTITY_ID_FORMAT
178+
179+
# The super init is not called because TemplateEntity and TriggerEntity will call AbstractTemplateEntity.__init__.
180+
# This ensures that the __init__ on AbstractTemplateEntity is not called twice.
181+
def __init__(self, config: dict[str, Any]) -> None: # pylint: disable=super-init-not-called
182+
"""Initialize the features."""
183+
184+
self._attr_device_class = config.get(CONF_DEVICE_CLASS)
185+
self._template: template.Template = config[CONF_STATE]
186+
self._delay_cancel: CALLBACK_TYPE | None = None
187+
188+
189+
class StateBinarySensorEntity(TemplateEntity, AbstractTemplateBinarySensor):
172190
"""A virtual binary sensor that triggers from another sensor."""
173191

174192
_attr_should_poll = False
175-
_entity_id_format = ENTITY_ID_FORMAT
176193

177194
def __init__(
178195
self,
@@ -182,19 +199,19 @@ def __init__(
182199
) -> None:
183200
"""Initialize the Template binary sensor."""
184201
TemplateEntity.__init__(self, hass, config, unique_id)
185-
186-
self._attr_device_class = config.get(CONF_DEVICE_CLASS)
187-
self._template: template.Template = config[CONF_STATE]
188-
self._delay_cancel = None
202+
AbstractTemplateBinarySensor.__init__(self, config)
189203
self._delay_on = None
190-
self._delay_on_raw = config.get(CONF_DELAY_ON)
204+
self._delay_on_template = config.get(CONF_DELAY_ON)
191205
self._delay_off = None
192-
self._delay_off_raw = config.get(CONF_DELAY_OFF)
206+
self._delay_off_template = config.get(CONF_DELAY_OFF)
193207

194208
async def async_added_to_hass(self) -> None:
195209
"""Restore state."""
196210
if (
197-
(self._delay_on_raw is not None or self._delay_off_raw is not None)
211+
(
212+
self._delay_on_template is not None
213+
or self._delay_off_template is not None
214+
)
198215
and (last_state := await self.async_get_last_state()) is not None
199216
and last_state.state not in (STATE_UNKNOWN, STATE_UNAVAILABLE)
200217
):
@@ -206,20 +223,20 @@ def _async_setup_templates(self) -> None:
206223
"""Set up templates."""
207224
self.add_template_attribute("_state", self._template, None, self._update_state)
208225

209-
if self._delay_on_raw is not None:
226+
if self._delay_on_template is not None:
210227
try:
211-
self._delay_on = cv.positive_time_period(self._delay_on_raw)
228+
self._delay_on = cv.positive_time_period(self._delay_on_template)
212229
except vol.Invalid:
213230
self.add_template_attribute(
214-
"_delay_on", self._delay_on_raw, cv.positive_time_period
231+
"_delay_on", self._delay_on_template, cv.positive_time_period
215232
)
216233

217-
if self._delay_off_raw is not None:
234+
if self._delay_off_template is not None:
218235
try:
219-
self._delay_off = cv.positive_time_period(self._delay_off_raw)
236+
self._delay_off = cv.positive_time_period(self._delay_off_template)
220237
except vol.Invalid:
221238
self.add_template_attribute(
222-
"_delay_off", self._delay_off_raw, cv.positive_time_period
239+
"_delay_off", self._delay_off_template, cv.positive_time_period
223240
)
224241

225242
super()._async_setup_templates()
@@ -259,12 +276,10 @@ def _set_state(_):
259276
self._delay_cancel = async_call_later(self.hass, delay, _set_state)
260277

261278

262-
class TriggerBinarySensorEntity(TriggerEntity, BinarySensorEntity, RestoreEntity):
279+
class TriggerBinarySensorEntity(TriggerEntity, AbstractTemplateBinarySensor):
263280
"""Sensor entity based on trigger data."""
264281

265-
_entity_id_format = ENTITY_ID_FORMAT
266282
domain = BINARY_SENSOR_DOMAIN
267-
extra_template_keys = (CONF_STATE,)
268283

269284
def __init__(
270285
self,
@@ -273,7 +288,8 @@ def __init__(
273288
config: dict,
274289
) -> None:
275290
"""Initialize the entity."""
276-
super().__init__(hass, coordinator, config)
291+
TriggerEntity.__init__(self, hass, coordinator, config)
292+
AbstractTemplateBinarySensor.__init__(self, config)
277293

278294
for key in (CONF_STATE, CONF_DELAY_ON, CONF_DELAY_OFF, CONF_AUTO_OFF):
279295
if isinstance(config.get(key), template.Template):
@@ -282,7 +298,6 @@ def __init__(
282298

283299
self._last_delay_from: bool | None = None
284300
self._last_delay_to: bool | None = None
285-
self._delay_cancel: CALLBACK_TYPE | None = None
286301
self._auto_off_cancel: CALLBACK_TYPE | None = None
287302
self._auto_off_time: datetime | None = None
288303

0 commit comments

Comments
 (0)