Create a Jewish Calendar entity (#120253)

* Set has_entity_name to true

* Move common code to jewish calendar service entity

* Remove already existing assignment

* Move data to common entity

* Remove description name

* Use config entry title instead of name for the device

* Address comments
This commit is contained in:
Tsvi Mostovicz 2024-06-23 20:55:27 +03:00 committed by GitHub
parent 034b5e88e0
commit 29da88d8f6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 68 additions and 55 deletions

View File

@ -6,7 +6,6 @@ from collections.abc import Callable
from dataclasses import dataclass from dataclasses import dataclass
import datetime as dt import datetime as dt
from datetime import datetime from datetime import datetime
from typing import Any
import hdate import hdate
from hdate.zmanim import Zmanim from hdate.zmanim import Zmanim
@ -16,18 +15,14 @@ from homeassistant.components.binary_sensor import (
BinarySensorEntityDescription, BinarySensorEntityDescription,
) )
from homeassistant.config_entries import ConfigEntry from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_LANGUAGE, CONF_LOCATION, EntityCategory from homeassistant.const import EntityCategory
from homeassistant.core import CALLBACK_TYPE, HomeAssistant, callback from homeassistant.core import CALLBACK_TYPE, HomeAssistant, callback
from homeassistant.helpers import event from homeassistant.helpers import event
from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.entity_platform import AddEntitiesCallback
import homeassistant.util.dt as dt_util import homeassistant.util.dt as dt_util
from .const import ( from .const import DOMAIN
CONF_CANDLE_LIGHT_MINUTES, from .entity import JewishCalendarEntity
CONF_HAVDALAH_OFFSET_MINUTES,
DEFAULT_NAME,
DOMAIN,
)
@dataclass(frozen=True) @dataclass(frozen=True)
@ -75,33 +70,19 @@ async def async_setup_entry(
entry = hass.data[DOMAIN][config_entry.entry_id] entry = hass.data[DOMAIN][config_entry.entry_id]
async_add_entities( async_add_entities(
JewishCalendarBinarySensor(config_entry.entry_id, entry, description) JewishCalendarBinarySensor(config_entry, entry, description)
for description in BINARY_SENSORS for description in BINARY_SENSORS
) )
class JewishCalendarBinarySensor(BinarySensorEntity): class JewishCalendarBinarySensor(JewishCalendarEntity, BinarySensorEntity):
"""Representation of an Jewish Calendar binary sensor.""" """Representation of an Jewish Calendar binary sensor."""
_attr_should_poll = False _attr_should_poll = False
_attr_entity_category = EntityCategory.DIAGNOSTIC _attr_entity_category = EntityCategory.DIAGNOSTIC
entity_description: JewishCalendarBinarySensorEntityDescription _update_unsub: CALLBACK_TYPE | None = None
def __init__( entity_description: JewishCalendarBinarySensorEntityDescription
self,
entry_id: str,
data: dict[str, Any],
description: JewishCalendarBinarySensorEntityDescription,
) -> None:
"""Initialize the binary sensor."""
self.entity_description = description
self._attr_name = f"{DEFAULT_NAME} {description.name}"
self._attr_unique_id = f"{entry_id}-{description.key}"
self._location = data[CONF_LOCATION]
self._hebrew = data[CONF_LANGUAGE] == "hebrew"
self._candle_lighting_offset = data[CONF_CANDLE_LIGHT_MINUTES]
self._havdalah_offset = data[CONF_HAVDALAH_OFFSET_MINUTES]
self._update_unsub: CALLBACK_TYPE | None = None
@property @property
def is_on(self) -> bool: def is_on(self) -> bool:

View File

@ -0,0 +1,41 @@
"""Entity representing a Jewish Calendar sensor."""
from typing import Any
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_LANGUAGE, CONF_LOCATION
from homeassistant.helpers.device_registry import DeviceEntryType, DeviceInfo
from homeassistant.helpers.entity import Entity, EntityDescription
from .const import (
CONF_CANDLE_LIGHT_MINUTES,
CONF_DIASPORA,
CONF_HAVDALAH_OFFSET_MINUTES,
DOMAIN,
)
class JewishCalendarEntity(Entity):
"""An HA implementation for Jewish Calendar entity."""
_attr_has_entity_name = True
def __init__(
self,
config_entry: ConfigEntry,
data: dict[str, Any],
description: EntityDescription,
) -> None:
"""Initialize a Jewish Calendar entity."""
self.entity_description = description
self._attr_unique_id = f"{config_entry.entry_id}_{description.key}"
self._attr_device_info = DeviceInfo(
entry_type=DeviceEntryType.SERVICE,
identifiers={(DOMAIN, config_entry.entry_id)},
name=config_entry.title,
)
self._location = data[CONF_LOCATION]
self._hebrew = data[CONF_LANGUAGE] == "hebrew"
self._candle_lighting_offset = data[CONF_CANDLE_LIGHT_MINUTES]
self._havdalah_offset = data[CONF_HAVDALAH_OFFSET_MINUTES]
self._diaspora = data[CONF_DIASPORA]

View File

@ -15,24 +15,14 @@ from homeassistant.components.sensor import (
SensorEntityDescription, SensorEntityDescription,
) )
from homeassistant.config_entries import ConfigEntry from homeassistant.config_entries import ConfigEntry
from homeassistant.const import ( from homeassistant.const import SUN_EVENT_SUNSET, EntityCategory
CONF_LANGUAGE,
CONF_LOCATION,
SUN_EVENT_SUNSET,
EntityCategory,
)
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.sun import get_astral_event_date from homeassistant.helpers.sun import get_astral_event_date
import homeassistant.util.dt as dt_util import homeassistant.util.dt as dt_util
from .const import ( from .const import DOMAIN
CONF_CANDLE_LIGHT_MINUTES, from .entity import JewishCalendarEntity
CONF_DIASPORA,
CONF_HAVDALAH_OFFSET_MINUTES,
DEFAULT_NAME,
DOMAIN,
)
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -185,37 +175,30 @@ async def async_setup_entry(
"""Set up the Jewish calendar sensors .""" """Set up the Jewish calendar sensors ."""
entry = hass.data[DOMAIN][config_entry.entry_id] entry = hass.data[DOMAIN][config_entry.entry_id]
sensors = [ sensors = [
JewishCalendarSensor(config_entry.entry_id, entry, description) JewishCalendarSensor(config_entry, entry, description)
for description in INFO_SENSORS for description in INFO_SENSORS
] ]
sensors.extend( sensors.extend(
JewishCalendarTimeSensor(config_entry.entry_id, entry, description) JewishCalendarTimeSensor(config_entry, entry, description)
for description in TIME_SENSORS for description in TIME_SENSORS
) )
async_add_entities(sensors) async_add_entities(sensors)
class JewishCalendarSensor(SensorEntity): class JewishCalendarSensor(JewishCalendarEntity, SensorEntity):
"""Representation of an Jewish calendar sensor.""" """Representation of an Jewish calendar sensor."""
_attr_entity_category = EntityCategory.DIAGNOSTIC _attr_entity_category = EntityCategory.DIAGNOSTIC
def __init__( def __init__(
self, self,
entry_id: str, config_entry: ConfigEntry,
data: dict[str, Any], data: dict[str, Any],
description: SensorEntityDescription, description: SensorEntityDescription,
) -> None: ) -> None:
"""Initialize the Jewish calendar sensor.""" """Initialize the Jewish calendar sensor."""
self.entity_description = description super().__init__(config_entry, data, description)
self._attr_name = f"{DEFAULT_NAME} {description.name}"
self._attr_unique_id = f"{entry_id}-{description.key}"
self._location = data[CONF_LOCATION]
self._hebrew = data[CONF_LANGUAGE] == "hebrew"
self._candle_lighting_offset = data[CONF_CANDLE_LIGHT_MINUTES]
self._havdalah_offset = data[CONF_HAVDALAH_OFFSET_MINUTES]
self._diaspora = data[CONF_DIASPORA]
self._attrs: dict[str, str] = {} self._attrs: dict[str, str] = {}
async def async_update(self) -> None: async def async_update(self) -> None:

View File

@ -10,6 +10,7 @@ from homeassistant.components.jewish_calendar.const import (
CONF_CANDLE_LIGHT_MINUTES, CONF_CANDLE_LIGHT_MINUTES,
CONF_DIASPORA, CONF_DIASPORA,
CONF_HAVDALAH_OFFSET_MINUTES, CONF_HAVDALAH_OFFSET_MINUTES,
DEFAULT_NAME,
DOMAIN, DOMAIN,
) )
from homeassistant.const import CONF_LANGUAGE, CONF_PLATFORM, STATE_OFF, STATE_ON from homeassistant.const import CONF_LANGUAGE, CONF_PLATFORM, STATE_OFF, STATE_ON
@ -192,6 +193,7 @@ async def test_issur_melacha_sensor(
with alter_time(test_time): with alter_time(test_time):
entry = MockConfigEntry( entry = MockConfigEntry(
title=DEFAULT_NAME,
domain=DOMAIN, domain=DOMAIN,
data={ data={
CONF_LANGUAGE: "english", CONF_LANGUAGE: "english",
@ -264,6 +266,7 @@ async def test_issur_melacha_sensor_update(
with alter_time(test_time): with alter_time(test_time):
entry = MockConfigEntry( entry = MockConfigEntry(
title=DEFAULT_NAME,
domain=DOMAIN, domain=DOMAIN,
data={ data={
CONF_LANGUAGE: "english", CONF_LANGUAGE: "english",

View File

@ -10,6 +10,7 @@ from homeassistant.components.jewish_calendar.const import (
CONF_CANDLE_LIGHT_MINUTES, CONF_CANDLE_LIGHT_MINUTES,
CONF_DIASPORA, CONF_DIASPORA,
CONF_HAVDALAH_OFFSET_MINUTES, CONF_HAVDALAH_OFFSET_MINUTES,
DEFAULT_NAME,
DOMAIN, DOMAIN,
) )
from homeassistant.const import CONF_LANGUAGE, CONF_PLATFORM from homeassistant.const import CONF_LANGUAGE, CONF_PLATFORM
@ -24,7 +25,7 @@ from tests.common import MockConfigEntry, async_fire_time_changed
async def test_jewish_calendar_min_config(hass: HomeAssistant) -> None: async def test_jewish_calendar_min_config(hass: HomeAssistant) -> None:
"""Test minimum jewish calendar configuration.""" """Test minimum jewish calendar configuration."""
entry = MockConfigEntry(domain=DOMAIN, data={}) entry = MockConfigEntry(title=DEFAULT_NAME, domain=DOMAIN, data={})
entry.add_to_hass(hass) entry.add_to_hass(hass)
await hass.config_entries.async_setup(entry.entry_id) await hass.config_entries.async_setup(entry.entry_id)
await hass.async_block_till_done() await hass.async_block_till_done()
@ -33,7 +34,9 @@ async def test_jewish_calendar_min_config(hass: HomeAssistant) -> None:
async def test_jewish_calendar_hebrew(hass: HomeAssistant) -> None: async def test_jewish_calendar_hebrew(hass: HomeAssistant) -> None:
"""Test jewish calendar sensor with language set to hebrew.""" """Test jewish calendar sensor with language set to hebrew."""
entry = MockConfigEntry(domain=DOMAIN, data={"language": "hebrew"}) entry = MockConfigEntry(
title=DEFAULT_NAME, domain=DOMAIN, data={"language": "hebrew"}
)
entry.add_to_hass(hass) entry.add_to_hass(hass)
await hass.config_entries.async_setup(entry.entry_id) await hass.config_entries.async_setup(entry.entry_id)
await hass.async_block_till_done() await hass.async_block_till_done()
@ -224,6 +227,7 @@ async def test_jewish_calendar_sensor(
with alter_time(test_time): with alter_time(test_time):
entry = MockConfigEntry( entry = MockConfigEntry(
title=DEFAULT_NAME,
domain=DOMAIN, domain=DOMAIN,
data={ data={
CONF_LANGUAGE: language, CONF_LANGUAGE: language,
@ -565,6 +569,7 @@ async def test_shabbat_times_sensor(
with alter_time(test_time): with alter_time(test_time):
entry = MockConfigEntry( entry = MockConfigEntry(
title=DEFAULT_NAME,
domain=DOMAIN, domain=DOMAIN,
data={ data={
CONF_LANGUAGE: language, CONF_LANGUAGE: language,
@ -625,7 +630,7 @@ async def test_omer_sensor(hass: HomeAssistant, test_time, result) -> None:
test_time = test_time.replace(tzinfo=dt_util.get_time_zone(hass.config.time_zone)) test_time = test_time.replace(tzinfo=dt_util.get_time_zone(hass.config.time_zone))
with alter_time(test_time): with alter_time(test_time):
entry = MockConfigEntry(domain=DOMAIN) entry = MockConfigEntry(title=DEFAULT_NAME, domain=DOMAIN)
entry.add_to_hass(hass) entry.add_to_hass(hass)
await hass.config_entries.async_setup(entry.entry_id) await hass.config_entries.async_setup(entry.entry_id)
await hass.async_block_till_done() await hass.async_block_till_done()
@ -660,7 +665,7 @@ async def test_dafyomi_sensor(hass: HomeAssistant, test_time, result) -> None:
test_time = test_time.replace(tzinfo=dt_util.get_time_zone(hass.config.time_zone)) test_time = test_time.replace(tzinfo=dt_util.get_time_zone(hass.config.time_zone))
with alter_time(test_time): with alter_time(test_time):
entry = MockConfigEntry(domain=DOMAIN) entry = MockConfigEntry(title=DEFAULT_NAME, domain=DOMAIN)
entry.add_to_hass(hass) entry.add_to_hass(hass)
await hass.config_entries.async_setup(entry.entry_id) await hass.config_entries.async_setup(entry.entry_id)
await hass.async_block_till_done() await hass.async_block_till_done()