mirror of
https://github.com/home-assistant/core
synced 2024-10-05 19:57:25 +00:00
Refactor Rest Binary sensor with ManualTriggerEntity (#97400)
* Refactor Rest Binary sensor w/ ManualTriggerEntity * test availability * review comments * Use super * Fix config
This commit is contained in:
parent
9b74321487
commit
4531dbbe62
|
@ -14,6 +14,8 @@ from homeassistant.components.binary_sensor import (
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
CONF_DEVICE_CLASS,
|
CONF_DEVICE_CLASS,
|
||||||
CONF_FORCE_UPDATE,
|
CONF_FORCE_UPDATE,
|
||||||
|
CONF_ICON,
|
||||||
|
CONF_NAME,
|
||||||
CONF_RESOURCE,
|
CONF_RESOURCE,
|
||||||
CONF_RESOURCE_TEMPLATE,
|
CONF_RESOURCE_TEMPLATE,
|
||||||
CONF_UNIQUE_ID,
|
CONF_UNIQUE_ID,
|
||||||
|
@ -24,7 +26,11 @@ from homeassistant.exceptions import PlatformNotReady
|
||||||
import homeassistant.helpers.config_validation as cv
|
import homeassistant.helpers.config_validation as cv
|
||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
from homeassistant.helpers.template import Template
|
from homeassistant.helpers.template import Template
|
||||||
from homeassistant.helpers.template_entity import TemplateEntity
|
from homeassistant.helpers.template_entity import (
|
||||||
|
CONF_AVAILABILITY,
|
||||||
|
CONF_PICTURE,
|
||||||
|
ManualTriggerEntity,
|
||||||
|
)
|
||||||
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
|
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
|
||||||
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator
|
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator
|
||||||
|
|
||||||
|
@ -42,6 +48,14 @@ PLATFORM_SCHEMA = vol.All(
|
||||||
cv.has_at_least_one_key(CONF_RESOURCE, CONF_RESOURCE_TEMPLATE), PLATFORM_SCHEMA
|
cv.has_at_least_one_key(CONF_RESOURCE, CONF_RESOURCE_TEMPLATE), PLATFORM_SCHEMA
|
||||||
)
|
)
|
||||||
|
|
||||||
|
TRIGGER_ENTITY_OPTIONS = (
|
||||||
|
CONF_AVAILABILITY,
|
||||||
|
CONF_DEVICE_CLASS,
|
||||||
|
CONF_ICON,
|
||||||
|
CONF_PICTURE,
|
||||||
|
CONF_UNIQUE_ID,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
async def async_setup_platform(
|
async def async_setup_platform(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
|
@ -74,7 +88,14 @@ async def async_setup_platform(
|
||||||
raise PlatformNotReady from rest.last_exception
|
raise PlatformNotReady from rest.last_exception
|
||||||
raise PlatformNotReady
|
raise PlatformNotReady
|
||||||
|
|
||||||
unique_id = conf.get(CONF_UNIQUE_ID)
|
name = conf.get(CONF_NAME) or Template(DEFAULT_BINARY_SENSOR_NAME, hass)
|
||||||
|
|
||||||
|
trigger_entity_config = {CONF_NAME: name}
|
||||||
|
|
||||||
|
for key in TRIGGER_ENTITY_OPTIONS:
|
||||||
|
if key not in conf:
|
||||||
|
continue
|
||||||
|
trigger_entity_config[key] = conf[key]
|
||||||
|
|
||||||
async_add_entities(
|
async_add_entities(
|
||||||
[
|
[
|
||||||
|
@ -83,13 +104,13 @@ async def async_setup_platform(
|
||||||
coordinator,
|
coordinator,
|
||||||
rest,
|
rest,
|
||||||
conf,
|
conf,
|
||||||
unique_id,
|
trigger_entity_config,
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class RestBinarySensor(RestEntity, TemplateEntity, BinarySensorEntity):
|
class RestBinarySensor(ManualTriggerEntity, RestEntity, BinarySensorEntity):
|
||||||
"""Representation of a REST binary sensor."""
|
"""Representation of a REST binary sensor."""
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
|
@ -98,9 +119,10 @@ class RestBinarySensor(RestEntity, TemplateEntity, BinarySensorEntity):
|
||||||
coordinator: DataUpdateCoordinator[None] | None,
|
coordinator: DataUpdateCoordinator[None] | None,
|
||||||
rest: RestData,
|
rest: RestData,
|
||||||
config: ConfigType,
|
config: ConfigType,
|
||||||
unique_id: str | None,
|
trigger_entity_config: ConfigType,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Initialize a REST binary sensor."""
|
"""Initialize a REST binary sensor."""
|
||||||
|
ManualTriggerEntity.__init__(self, hass, trigger_entity_config)
|
||||||
RestEntity.__init__(
|
RestEntity.__init__(
|
||||||
self,
|
self,
|
||||||
coordinator,
|
coordinator,
|
||||||
|
@ -108,19 +130,17 @@ class RestBinarySensor(RestEntity, TemplateEntity, BinarySensorEntity):
|
||||||
config.get(CONF_RESOURCE_TEMPLATE),
|
config.get(CONF_RESOURCE_TEMPLATE),
|
||||||
config[CONF_FORCE_UPDATE],
|
config[CONF_FORCE_UPDATE],
|
||||||
)
|
)
|
||||||
TemplateEntity.__init__(
|
|
||||||
self,
|
|
||||||
hass,
|
|
||||||
config=config,
|
|
||||||
fallback_name=DEFAULT_BINARY_SENSOR_NAME,
|
|
||||||
unique_id=unique_id,
|
|
||||||
)
|
|
||||||
self._previous_data = None
|
self._previous_data = None
|
||||||
self._value_template: Template | None = config.get(CONF_VALUE_TEMPLATE)
|
self._value_template: Template | None = config.get(CONF_VALUE_TEMPLATE)
|
||||||
if (value_template := self._value_template) is not None:
|
if (value_template := self._value_template) is not None:
|
||||||
value_template.hass = hass
|
value_template.hass = hass
|
||||||
|
|
||||||
self._attr_device_class = config.get(CONF_DEVICE_CLASS)
|
@property
|
||||||
|
def available(self) -> bool:
|
||||||
|
"""Return if entity is available."""
|
||||||
|
available1 = RestEntity.available.fget(self) # type: ignore[attr-defined]
|
||||||
|
available2 = ManualTriggerEntity.available.fget(self) # type: ignore[attr-defined]
|
||||||
|
return bool(available1 and available2)
|
||||||
|
|
||||||
def _update_from_rest_data(self) -> None:
|
def _update_from_rest_data(self) -> None:
|
||||||
"""Update state from the rest data."""
|
"""Update state from the rest data."""
|
||||||
|
@ -130,6 +150,8 @@ class RestBinarySensor(RestEntity, TemplateEntity, BinarySensorEntity):
|
||||||
|
|
||||||
response = self.rest.data
|
response = self.rest.data
|
||||||
|
|
||||||
|
raw_value = response
|
||||||
|
|
||||||
if self._value_template is not None:
|
if self._value_template is not None:
|
||||||
response = self._value_template.async_render_with_possible_json_value(
|
response = self._value_template.async_render_with_possible_json_value(
|
||||||
self.rest.data, False
|
self.rest.data, False
|
||||||
|
@ -144,3 +166,6 @@ class RestBinarySensor(RestEntity, TemplateEntity, BinarySensorEntity):
|
||||||
"open": True,
|
"open": True,
|
||||||
"yes": True,
|
"yes": True,
|
||||||
}.get(response.lower(), False)
|
}.get(response.lower(), False)
|
||||||
|
|
||||||
|
self._process_manual_data(raw_value)
|
||||||
|
self.async_write_ha_state()
|
||||||
|
|
|
@ -28,6 +28,7 @@ from homeassistant.const import (
|
||||||
)
|
)
|
||||||
import homeassistant.helpers.config_validation as cv
|
import homeassistant.helpers.config_validation as cv
|
||||||
from homeassistant.helpers.template_entity import (
|
from homeassistant.helpers.template_entity import (
|
||||||
|
CONF_AVAILABILITY,
|
||||||
TEMPLATE_ENTITY_BASE_SCHEMA,
|
TEMPLATE_ENTITY_BASE_SCHEMA,
|
||||||
TEMPLATE_SENSOR_BASE_SCHEMA,
|
TEMPLATE_SENSOR_BASE_SCHEMA,
|
||||||
)
|
)
|
||||||
|
@ -82,6 +83,7 @@ BINARY_SENSOR_SCHEMA = {
|
||||||
vol.Optional(CONF_DEVICE_CLASS): BINARY_SENSOR_DEVICE_CLASSES_SCHEMA,
|
vol.Optional(CONF_DEVICE_CLASS): BINARY_SENSOR_DEVICE_CLASSES_SCHEMA,
|
||||||
vol.Optional(CONF_VALUE_TEMPLATE): cv.template,
|
vol.Optional(CONF_VALUE_TEMPLATE): cv.template,
|
||||||
vol.Optional(CONF_FORCE_UPDATE, default=DEFAULT_FORCE_UPDATE): cv.boolean,
|
vol.Optional(CONF_FORCE_UPDATE, default=DEFAULT_FORCE_UPDATE): cv.boolean,
|
||||||
|
vol.Optional(CONF_AVAILABILITY): cv.template,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -564,6 +564,7 @@ class TriggerBaseEntity(Entity):
|
||||||
|
|
||||||
async def async_added_to_hass(self) -> None:
|
async def async_added_to_hass(self) -> None:
|
||||||
"""Handle being added to Home Assistant."""
|
"""Handle being added to Home Assistant."""
|
||||||
|
await super().async_added_to_hass()
|
||||||
template_attach(self.hass, self._config)
|
template_attach(self.hass, self._config)
|
||||||
|
|
||||||
def _set_unique_id(self, unique_id: str | None) -> None:
|
def _set_unique_id(self, unique_id: str | None) -> None:
|
||||||
|
|
|
@ -500,3 +500,27 @@ async def test_entity_config(hass: HomeAssistant) -> None:
|
||||||
"friendly_name": "REST Binary Sensor",
|
"friendly_name": "REST Binary Sensor",
|
||||||
"icon": "mdi:one_two_three",
|
"icon": "mdi:one_two_three",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@respx.mock
|
||||||
|
async def test_availability_in_config(hass: HomeAssistant) -> None:
|
||||||
|
"""Test entity configuration."""
|
||||||
|
|
||||||
|
config = {
|
||||||
|
BINARY_SENSOR_DOMAIN: {
|
||||||
|
# REST configuration
|
||||||
|
"platform": DOMAIN,
|
||||||
|
"method": "GET",
|
||||||
|
"resource": "http://localhost",
|
||||||
|
# Entity configuration
|
||||||
|
"availability": "{{value==1}}",
|
||||||
|
"name": "{{'REST' + ' ' + 'Binary Sensor'}}",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
respx.get("http://localhost") % HTTPStatus.OK
|
||||||
|
assert await async_setup_component(hass, BINARY_SENSOR_DOMAIN, config)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
state = hass.states.get("binary_sensor.rest_binary_sensor")
|
||||||
|
assert state.state == STATE_UNAVAILABLE
|
||||||
|
|
Loading…
Reference in a new issue