Compare commits

..

1 Commits

Author SHA1 Message Date
epenet
46a16a286b Use runtime_data in starline integration
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 05:56:06 +00:00
11 changed files with 40 additions and 69 deletions

View File

@@ -7,7 +7,6 @@ from ring_doorbell import RingCapability, RingEvent as RingAlert
from ring_doorbell.const import KIND_DING, KIND_INTERCOM_UNLOCK, KIND_MOTION
from homeassistant.components.event import (
DoorbellEventType,
EventDeviceClass,
EventEntity,
EventEntityDescription,
@@ -35,7 +34,7 @@ EVENT_DESCRIPTIONS: tuple[RingEventEntityDescription, ...] = (
key=KIND_DING,
translation_key=KIND_DING,
device_class=EventDeviceClass.DOORBELL,
event_types=[DoorbellEventType.RING],
event_types=[KIND_DING],
capability=RingCapability.DING,
),
RingEventEntityDescription(
@@ -101,10 +100,7 @@ class RingEvent(RingBaseEntity[RingListenCoordinator, RingDeviceT], EventEntity)
@callback
def _handle_coordinator_update(self) -> None:
if (alert := self._get_coordinator_alert()) and not alert.is_update:
if alert.kind == KIND_DING:
self._async_handle_event(DoorbellEventType.RING)
else:
self._async_handle_event(alert.kind)
self._async_handle_event(alert.kind)
super()._handle_coordinator_update()
@property

View File

@@ -73,14 +73,7 @@
},
"event": {
"ding": {
"name": "Ding",
"state_attributes": {
"event_type": {
"state": {
"ring": "[%key:component::event::entity_component::doorbell::state_attributes::event_type::state::ring%]"
}
}
}
"name": "Ding"
},
"intercom_unlock": {
"name": "Intercom unlock"

View File

@@ -22,8 +22,10 @@ from .const import (
SERVICE_UPDATE_STATE,
)
type StarlineConfigEntry = ConfigEntry[StarlineAccount]
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
async def async_setup_entry(hass: HomeAssistant, entry: StarlineConfigEntry) -> bool:
"""Set up the StarLine device from a config entry."""
account = StarlineAccount(hass, entry)
await account.update()
@@ -31,9 +33,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
if not account.api.available:
raise ConfigEntryNotReady
if DOMAIN not in hass.data:
hass.data[DOMAIN] = {}
hass.data[DOMAIN][entry.entry_id] = account
entry.runtime_data = account
device_registry = dr.async_get(hass)
for device in account.api.devices.values():
@@ -92,20 +92,23 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
return True
async def async_unload_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> bool:
async def async_unload_entry(
hass: HomeAssistant, config_entry: StarlineConfigEntry
) -> bool:
"""Unload a config entry."""
unload_ok = await hass.config_entries.async_unload_platforms(
config_entry, PLATFORMS
)
account: StarlineAccount = hass.data[DOMAIN][config_entry.entry_id]
account.unload()
config_entry.runtime_data.unload()
return unload_ok
async def async_options_updated(hass: HomeAssistant, config_entry: ConfigEntry) -> None:
async def async_options_updated(
hass: HomeAssistant, config_entry: StarlineConfigEntry
) -> None:
"""Triggered by config entry options updates."""
account: StarlineAccount = hass.data[DOMAIN][config_entry.entry_id]
account = config_entry.runtime_data
scan_interval = config_entry.options.get(CONF_SCAN_INTERVAL, DEFAULT_SCAN_INTERVAL)
scan_obd_interval = config_entry.options.get(
CONF_SCAN_OBD_INTERVAL, DEFAULT_SCAN_OBD_INTERVAL

View File

@@ -7,13 +7,12 @@ from homeassistant.components.binary_sensor import (
BinarySensorEntity,
BinarySensorEntityDescription,
)
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import EntityCategory
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
from . import StarlineConfigEntry
from .account import StarlineAccount, StarlineDevice
from .const import DOMAIN
from .entity import StarlineEntity
BINARY_SENSOR_TYPES: tuple[BinarySensorEntityDescription, ...] = (
@@ -71,11 +70,11 @@ BINARY_SENSOR_TYPES: tuple[BinarySensorEntityDescription, ...] = (
async def async_setup_entry(
hass: HomeAssistant,
entry: ConfigEntry,
entry: StarlineConfigEntry,
async_add_entities: AddConfigEntryEntitiesCallback,
) -> None:
"""Set up the StarLine sensors."""
account: StarlineAccount = hass.data[DOMAIN][entry.entry_id]
account = entry.runtime_data
entities = [
sensor
for device in account.api.devices.values()

View File

@@ -3,12 +3,11 @@
from __future__ import annotations
from homeassistant.components.button import ButtonEntity, ButtonEntityDescription
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
from . import StarlineConfigEntry
from .account import StarlineAccount, StarlineDevice
from .const import DOMAIN
from .entity import StarlineEntity
BUTTON_TYPES: tuple[ButtonEntityDescription, ...] = (
@@ -35,11 +34,11 @@ BUTTON_TYPES: tuple[ButtonEntityDescription, ...] = (
async def async_setup_entry(
hass: HomeAssistant,
entry: ConfigEntry,
entry: StarlineConfigEntry,
async_add_entities: AddConfigEntryEntitiesCallback,
) -> None:
"""Set up the StarLine button."""
account: StarlineAccount = hass.data[DOMAIN][entry.entry_id]
account = entry.runtime_data
async_add_entities(
StarlineButton(account, device, description)
for device in account.api.devices.values()

View File

@@ -3,23 +3,22 @@
from typing import Any
from homeassistant.components.device_tracker import TrackerEntity
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
from homeassistant.helpers.restore_state import RestoreEntity
from . import StarlineConfigEntry
from .account import StarlineAccount, StarlineDevice
from .const import DOMAIN
from .entity import StarlineEntity
async def async_setup_entry(
hass: HomeAssistant,
entry: ConfigEntry,
entry: StarlineConfigEntry,
async_add_entities: AddConfigEntryEntitiesCallback,
) -> None:
"""Set up StarLine entry."""
account: StarlineAccount = hass.data[DOMAIN][entry.entry_id]
account = entry.runtime_data
async_add_entities(
StarlineDeviceTracker(account, device)
for device in account.api.devices.values()

View File

@@ -5,22 +5,21 @@ from __future__ import annotations
from typing import Any
from homeassistant.components.lock import LockEntity
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
from . import StarlineConfigEntry
from .account import StarlineAccount, StarlineDevice
from .const import DOMAIN
from .entity import StarlineEntity
async def async_setup_entry(
hass: HomeAssistant,
entry: ConfigEntry,
entry: StarlineConfigEntry,
async_add_entities: AddConfigEntryEntitiesCallback,
) -> None:
"""Set up the StarLine lock."""
account: StarlineAccount = hass.data[DOMAIN][entry.entry_id]
account = entry.runtime_data
entities = []
for device in account.api.devices.values():
if device.support_state:

View File

@@ -10,7 +10,6 @@ from homeassistant.components.sensor import (
SensorEntityDescription,
SensorStateClass,
)
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import (
PERCENTAGE,
EntityCategory,
@@ -23,8 +22,8 @@ from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
from homeassistant.helpers.icon import icon_for_battery_level, icon_for_signal_level
from . import StarlineConfigEntry
from .account import StarlineAccount, StarlineDevice
from .const import DOMAIN
from .entity import StarlineEntity
SENSOR_TYPES: tuple[SensorEntityDescription, ...] = (
@@ -91,11 +90,11 @@ SENSOR_TYPES: tuple[SensorEntityDescription, ...] = (
async def async_setup_entry(
hass: HomeAssistant,
entry: ConfigEntry,
entry: StarlineConfigEntry,
async_add_entities: AddConfigEntryEntitiesCallback,
) -> None:
"""Set up the StarLine sensors."""
account: StarlineAccount = hass.data[DOMAIN][entry.entry_id]
account = entry.runtime_data
entities = [
sensor
for device in account.api.devices.values()

View File

@@ -5,12 +5,11 @@ from __future__ import annotations
from typing import Any
from homeassistant.components.switch import SwitchEntity, SwitchEntityDescription
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
from . import StarlineConfigEntry
from .account import StarlineAccount, StarlineDevice
from .const import DOMAIN
from .entity import StarlineEntity
SWITCH_TYPES: tuple[SwitchEntityDescription, ...] = (
@@ -35,11 +34,11 @@ SWITCH_TYPES: tuple[SwitchEntityDescription, ...] = (
async def async_setup_entry(
hass: HomeAssistant,
entry: ConfigEntry,
entry: StarlineConfigEntry,
async_add_entities: AddConfigEntryEntitiesCallback,
) -> None:
"""Set up the StarLine switch."""
account: StarlineAccount = hass.data[DOMAIN][entry.entry_id]
account = entry.runtime_data
entities = [
switch
for device in account.api.devices.values()

View File

@@ -7,7 +7,7 @@
'area_id': None,
'capabilities': dict({
'event_types': list([
<DoorbellEventType.RING: 'ring'>,
'ding',
]),
}),
'config_entry_id': <ANY>,
@@ -47,7 +47,7 @@
'device_class': 'doorbell',
'event_type': None,
'event_types': list([
<DoorbellEventType.RING: 'ring'>,
'ding',
]),
'friendly_name': 'Front Door Ding',
}),
@@ -187,7 +187,7 @@
'area_id': None,
'capabilities': dict({
'event_types': list([
<DoorbellEventType.RING: 'ring'>,
'ding',
]),
}),
'config_entry_id': <ANY>,
@@ -227,7 +227,7 @@
'device_class': 'doorbell',
'event_type': None,
'event_types': list([
<DoorbellEventType.RING: 'ring'>,
'ding',
]),
'friendly_name': 'Ingress Ding',
}),

View File

@@ -9,7 +9,6 @@ import pytest
from ring_doorbell import Ring
from syrupy.assertion import SnapshotAssertion
from homeassistant.components.event import ATTR_EVENT_TYPE, DoorbellEventType
from homeassistant.components.ring.binary_sensor import RingEvent
from homeassistant.components.ring.coordinator import RingEventListener
from homeassistant.const import Platform
@@ -36,38 +35,26 @@ async def test_states(
@pytest.mark.parametrize(
("device_id", "device_name", "alert_kind", "device_class", "event_type"),
("device_id", "device_name", "alert_kind", "device_class"),
[
pytest.param(
FRONT_DOOR_DEVICE_ID,
"front_door",
"motion",
"motion",
"motion",
id="front_door_motion",
),
pytest.param(
FRONT_DOOR_DEVICE_ID,
"front_door",
"ding",
"doorbell",
DoorbellEventType.RING,
id="front_door_ding",
FRONT_DOOR_DEVICE_ID, "front_door", "ding", "doorbell", id="front_door_ding"
),
pytest.param(
INGRESS_DEVICE_ID,
"ingress",
"ding",
"doorbell",
DoorbellEventType.RING,
id="ingress_ding",
INGRESS_DEVICE_ID, "ingress", "ding", "doorbell", id="ingress_ding"
),
pytest.param(
INGRESS_DEVICE_ID,
"ingress",
"intercom_unlock",
"button",
"intercom_unlock",
id="ingress_unlock",
),
],
@@ -81,7 +68,6 @@ async def test_event(
device_name: str,
alert_kind: str,
device_class: str,
event_type: str,
) -> None:
"""Test the Ring event platforms."""
@@ -110,4 +96,3 @@ async def test_event(
state = hass.states.get(entity_id)
assert state is not None
assert state.state == start_time_str
assert state.attributes[ATTR_EVENT_TYPE] == event_type