Move philips_js coordinator to separate module (#117561)

This commit is contained in:
epenet 2024-05-18 10:21:22 +02:00 committed by GitHub
parent 7ceaf2d3f0
commit a904557bbb
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 157 additions and 135 deletions

View file

@ -1020,6 +1020,7 @@ omit =
homeassistant/components/permobil/entity.py
homeassistant/components/permobil/sensor.py
homeassistant/components/philips_js/__init__.py
homeassistant/components/philips_js/coordinator.py
homeassistant/components/philips_js/light.py
homeassistant/components/philips_js/media_player.py
homeassistant/components/philips_js/remote.py

View file

@ -2,18 +2,9 @@
from __future__ import annotations
import asyncio
from collections.abc import Mapping
from datetime import timedelta
import logging
from typing import Any
from haphilipsjs import (
AutenticationFailure,
ConnectionFailure,
GeneralFailure,
PhilipsTV,
)
from haphilipsjs import PhilipsTV
from haphilipsjs.typing import SystemType
from homeassistant.config_entries import ConfigEntry
@ -24,13 +15,10 @@ from homeassistant.const import (
CONF_USERNAME,
Platform,
)
from homeassistant.core import HomeAssistant, callback
from homeassistant.exceptions import ConfigEntryAuthFailed
from homeassistant.helpers.debounce import Debouncer
from homeassistant.helpers.device_registry import DeviceInfo
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
from homeassistant.core import HomeAssistant
from .const import CONF_ALLOW_NOTIFY, CONF_SYSTEM, DOMAIN
from .const import CONF_SYSTEM
from .coordinator import PhilipsTVDataUpdateCoordinator
PLATFORMS = [
Platform.BINARY_SENSOR,
@ -42,7 +30,7 @@ PLATFORMS = [
LOGGER = logging.getLogger(__name__)
PhilipsTVConfigEntry = ConfigEntry["PhilipsTVDataUpdateCoordinator"]
PhilipsTVConfigEntry = ConfigEntry[PhilipsTVDataUpdateCoordinator]
async def async_setup_entry(hass: HomeAssistant, entry: PhilipsTVConfigEntry) -> bool:
@ -81,115 +69,3 @@ async def async_update_entry(hass: HomeAssistant, entry: PhilipsTVConfigEntry) -
async def async_unload_entry(hass: HomeAssistant, entry: PhilipsTVConfigEntry) -> bool:
"""Unload a config entry."""
return await hass.config_entries.async_unload_platforms(entry, PLATFORMS)
class PhilipsTVDataUpdateCoordinator(DataUpdateCoordinator[None]): # pylint: disable=hass-enforce-coordinator-module
"""Coordinator to update data."""
config_entry: ConfigEntry
def __init__(
self, hass: HomeAssistant, api: PhilipsTV, options: Mapping[str, Any]
) -> None:
"""Set up the coordinator."""
self.api = api
self.options = options
self._notify_future: asyncio.Task | None = None
super().__init__(
hass,
LOGGER,
name=DOMAIN,
update_interval=timedelta(seconds=30),
request_refresh_debouncer=Debouncer(
hass, LOGGER, cooldown=2.0, immediate=False
),
)
@property
def device_info(self) -> DeviceInfo:
"""Return device info."""
return DeviceInfo(
identifiers={
(DOMAIN, self.unique_id),
},
manufacturer="Philips",
model=self.system.get("model"),
name=self.system["name"],
sw_version=self.system.get("softwareversion"),
)
@property
def system(self) -> SystemType:
"""Return the system descriptor."""
if self.api.system:
return self.api.system
return self.config_entry.data[CONF_SYSTEM]
@property
def unique_id(self) -> str:
"""Return the system descriptor."""
entry = self.config_entry
if entry.unique_id:
return entry.unique_id
assert entry.entry_id
return entry.entry_id
@property
def _notify_wanted(self):
"""Return if the notify feature should be active.
We only run it when TV is considered fully on. When powerstate is in standby, the TV
will go in low power states and seemingly break the http server in odd ways.
"""
return (
self.api.on
and self.api.powerstate == "On"
and self.api.notify_change_supported
and self.options.get(CONF_ALLOW_NOTIFY, False)
)
async def _notify_task(self):
while self._notify_wanted:
try:
res = await self.api.notifyChange(130)
except (ConnectionFailure, AutenticationFailure):
res = None
if res:
self.async_set_updated_data(None)
elif res is None:
LOGGER.debug("Aborting notify due to unexpected return")
break
@callback
def _async_notify_stop(self):
if self._notify_future:
self._notify_future.cancel()
self._notify_future = None
@callback
def _async_notify_schedule(self):
if self._notify_future and not self._notify_future.done():
return
if self._notify_wanted:
self._notify_future = asyncio.create_task(self._notify_task())
@callback
def _unschedule_refresh(self) -> None:
"""Remove data update."""
super()._unschedule_refresh()
self._async_notify_stop()
async def _async_update_data(self):
"""Fetch the latest data from the source."""
try:
await self.api.update()
self._async_notify_schedule()
except ConnectionFailure:
pass
except AutenticationFailure as exception:
raise ConfigEntryAuthFailed(str(exception)) from exception
except GeneralFailure as exception:
raise UpdateFailed(str(exception)) from exception

View file

@ -13,7 +13,8 @@ from homeassistant.components.binary_sensor import (
from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from . import PhilipsTVConfigEntry, PhilipsTVDataUpdateCoordinator
from . import PhilipsTVConfigEntry
from .coordinator import PhilipsTVDataUpdateCoordinator
from .entity import PhilipsJsEntity

View file

@ -0,0 +1,140 @@
"""Coordinator for the Philips TV integration."""
from __future__ import annotations
import asyncio
from collections.abc import Mapping
from datetime import timedelta
import logging
from typing import Any
from haphilipsjs import (
AutenticationFailure,
ConnectionFailure,
GeneralFailure,
PhilipsTV,
)
from haphilipsjs.typing import SystemType
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant, callback
from homeassistant.exceptions import ConfigEntryAuthFailed
from homeassistant.helpers.debounce import Debouncer
from homeassistant.helpers.device_registry import DeviceInfo
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
from .const import CONF_ALLOW_NOTIFY, CONF_SYSTEM, DOMAIN
_LOGGER = logging.getLogger(__name__)
class PhilipsTVDataUpdateCoordinator(DataUpdateCoordinator[None]):
"""Coordinator to update data."""
config_entry: ConfigEntry
def __init__(
self, hass: HomeAssistant, api: PhilipsTV, options: Mapping[str, Any]
) -> None:
"""Set up the coordinator."""
self.api = api
self.options = options
self._notify_future: asyncio.Task | None = None
super().__init__(
hass,
_LOGGER,
name=DOMAIN,
update_interval=timedelta(seconds=30),
request_refresh_debouncer=Debouncer(
hass, _LOGGER, cooldown=2.0, immediate=False
),
)
@property
def device_info(self) -> DeviceInfo:
"""Return device info."""
return DeviceInfo(
identifiers={
(DOMAIN, self.unique_id),
},
manufacturer="Philips",
model=self.system.get("model"),
name=self.system["name"],
sw_version=self.system.get("softwareversion"),
)
@property
def system(self) -> SystemType:
"""Return the system descriptor."""
if self.api.system:
return self.api.system
return self.config_entry.data[CONF_SYSTEM]
@property
def unique_id(self) -> str:
"""Return the system descriptor."""
entry = self.config_entry
if entry.unique_id:
return entry.unique_id
assert entry.entry_id
return entry.entry_id
@property
def _notify_wanted(self):
"""Return if the notify feature should be active.
We only run it when TV is considered fully on. When powerstate is in standby, the TV
will go in low power states and seemingly break the http server in odd ways.
"""
return (
self.api.on
and self.api.powerstate == "On"
and self.api.notify_change_supported
and self.options.get(CONF_ALLOW_NOTIFY, False)
)
async def _notify_task(self):
while self._notify_wanted:
try:
res = await self.api.notifyChange(130)
except (ConnectionFailure, AutenticationFailure):
res = None
if res:
self.async_set_updated_data(None)
elif res is None:
_LOGGER.debug("Aborting notify due to unexpected return")
break
@callback
def _async_notify_stop(self):
if self._notify_future:
self._notify_future.cancel()
self._notify_future = None
@callback
def _async_notify_schedule(self):
if self._notify_future and not self._notify_future.done():
return
if self._notify_wanted:
self._notify_future = asyncio.create_task(self._notify_task())
@callback
def _unschedule_refresh(self) -> None:
"""Remove data update."""
super()._unschedule_refresh()
self._async_notify_stop()
async def _async_update_data(self):
"""Fetch the latest data from the source."""
try:
await self.api.update()
self._async_notify_schedule()
except ConnectionFailure:
pass
except AutenticationFailure as exception:
raise ConfigEntryAuthFailed(str(exception)) from exception
except GeneralFailure as exception:
raise UpdateFailed(str(exception)) from exception

View file

@ -4,7 +4,7 @@ from __future__ import annotations
from homeassistant.helpers.update_coordinator import CoordinatorEntity
from . import PhilipsTVDataUpdateCoordinator
from .coordinator import PhilipsTVDataUpdateCoordinator
class PhilipsJsEntity(CoordinatorEntity[PhilipsTVDataUpdateCoordinator]):

View file

@ -21,7 +21,8 @@ from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.util.color import color_hsv_to_RGB, color_RGB_to_hsv
from . import PhilipsTVConfigEntry, PhilipsTVDataUpdateCoordinator
from . import PhilipsTVConfigEntry
from .coordinator import PhilipsTVDataUpdateCoordinator
from .entity import PhilipsJsEntity
EFFECT_PARTITION = ": "

View file

@ -21,7 +21,8 @@ from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.trigger import PluggableAction
from . import LOGGER as _LOGGER, PhilipsTVConfigEntry, PhilipsTVDataUpdateCoordinator
from . import LOGGER as _LOGGER, PhilipsTVConfigEntry
from .coordinator import PhilipsTVDataUpdateCoordinator
from .entity import PhilipsJsEntity
from .helpers import async_get_turn_on_trigger

View file

@ -16,7 +16,8 @@ from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.trigger import PluggableAction
from . import LOGGER, PhilipsTVConfigEntry, PhilipsTVDataUpdateCoordinator
from . import LOGGER, PhilipsTVConfigEntry
from .coordinator import PhilipsTVDataUpdateCoordinator
from .entity import PhilipsJsEntity
from .helpers import async_get_turn_on_trigger

View file

@ -8,7 +8,8 @@ from homeassistant.components.switch import SwitchEntity
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from . import PhilipsTVConfigEntry, PhilipsTVDataUpdateCoordinator
from . import PhilipsTVConfigEntry
from .coordinator import PhilipsTVDataUpdateCoordinator
from .entity import PhilipsJsEntity
HUE_POWER_OFF = "Off"