mirror of
https://github.com/home-assistant/core.git
synced 2025-07-21 04:07:08 +00:00
Move philips_js coordinator to separate module (#117561)
This commit is contained in:
parent
7ceaf2d3f0
commit
a904557bbb
@ -1020,6 +1020,7 @@ omit =
|
|||||||
homeassistant/components/permobil/entity.py
|
homeassistant/components/permobil/entity.py
|
||||||
homeassistant/components/permobil/sensor.py
|
homeassistant/components/permobil/sensor.py
|
||||||
homeassistant/components/philips_js/__init__.py
|
homeassistant/components/philips_js/__init__.py
|
||||||
|
homeassistant/components/philips_js/coordinator.py
|
||||||
homeassistant/components/philips_js/light.py
|
homeassistant/components/philips_js/light.py
|
||||||
homeassistant/components/philips_js/media_player.py
|
homeassistant/components/philips_js/media_player.py
|
||||||
homeassistant/components/philips_js/remote.py
|
homeassistant/components/philips_js/remote.py
|
||||||
|
@ -2,18 +2,9 @@
|
|||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import asyncio
|
|
||||||
from collections.abc import Mapping
|
|
||||||
from datetime import timedelta
|
|
||||||
import logging
|
import logging
|
||||||
from typing import Any
|
|
||||||
|
|
||||||
from haphilipsjs import (
|
from haphilipsjs import PhilipsTV
|
||||||
AutenticationFailure,
|
|
||||||
ConnectionFailure,
|
|
||||||
GeneralFailure,
|
|
||||||
PhilipsTV,
|
|
||||||
)
|
|
||||||
from haphilipsjs.typing import SystemType
|
from haphilipsjs.typing import SystemType
|
||||||
|
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
@ -24,13 +15,10 @@ from homeassistant.const import (
|
|||||||
CONF_USERNAME,
|
CONF_USERNAME,
|
||||||
Platform,
|
Platform,
|
||||||
)
|
)
|
||||||
from homeassistant.core import HomeAssistant, callback
|
from homeassistant.core import HomeAssistant
|
||||||
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
|
from .const import CONF_SYSTEM
|
||||||
|
from .coordinator import PhilipsTVDataUpdateCoordinator
|
||||||
|
|
||||||
PLATFORMS = [
|
PLATFORMS = [
|
||||||
Platform.BINARY_SENSOR,
|
Platform.BINARY_SENSOR,
|
||||||
@ -42,7 +30,7 @@ PLATFORMS = [
|
|||||||
|
|
||||||
LOGGER = logging.getLogger(__name__)
|
LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
PhilipsTVConfigEntry = ConfigEntry["PhilipsTVDataUpdateCoordinator"]
|
PhilipsTVConfigEntry = ConfigEntry[PhilipsTVDataUpdateCoordinator]
|
||||||
|
|
||||||
|
|
||||||
async def async_setup_entry(hass: HomeAssistant, entry: PhilipsTVConfigEntry) -> bool:
|
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:
|
async def async_unload_entry(hass: HomeAssistant, entry: PhilipsTVConfigEntry) -> bool:
|
||||||
"""Unload a config entry."""
|
"""Unload a config entry."""
|
||||||
return await hass.config_entries.async_unload_platforms(entry, PLATFORMS)
|
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
|
|
||||||
|
@ -13,7 +13,8 @@ from homeassistant.components.binary_sensor import (
|
|||||||
from homeassistant.core import HomeAssistant, callback
|
from homeassistant.core import HomeAssistant, callback
|
||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
|
|
||||||
from . import PhilipsTVConfigEntry, PhilipsTVDataUpdateCoordinator
|
from . import PhilipsTVConfigEntry
|
||||||
|
from .coordinator import PhilipsTVDataUpdateCoordinator
|
||||||
from .entity import PhilipsJsEntity
|
from .entity import PhilipsJsEntity
|
||||||
|
|
||||||
|
|
||||||
|
140
homeassistant/components/philips_js/coordinator.py
Normal file
140
homeassistant/components/philips_js/coordinator.py
Normal 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
|
@ -4,7 +4,7 @@ from __future__ import annotations
|
|||||||
|
|
||||||
from homeassistant.helpers.update_coordinator import CoordinatorEntity
|
from homeassistant.helpers.update_coordinator import CoordinatorEntity
|
||||||
|
|
||||||
from . import PhilipsTVDataUpdateCoordinator
|
from .coordinator import PhilipsTVDataUpdateCoordinator
|
||||||
|
|
||||||
|
|
||||||
class PhilipsJsEntity(CoordinatorEntity[PhilipsTVDataUpdateCoordinator]):
|
class PhilipsJsEntity(CoordinatorEntity[PhilipsTVDataUpdateCoordinator]):
|
||||||
|
@ -21,7 +21,8 @@ from homeassistant.exceptions import HomeAssistantError
|
|||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
from homeassistant.util.color import color_hsv_to_RGB, color_RGB_to_hsv
|
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
|
from .entity import PhilipsJsEntity
|
||||||
|
|
||||||
EFFECT_PARTITION = ": "
|
EFFECT_PARTITION = ": "
|
||||||
|
@ -21,7 +21,8 @@ from homeassistant.exceptions import HomeAssistantError
|
|||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
from homeassistant.helpers.trigger import PluggableAction
|
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 .entity import PhilipsJsEntity
|
||||||
from .helpers import async_get_turn_on_trigger
|
from .helpers import async_get_turn_on_trigger
|
||||||
|
|
||||||
|
@ -16,7 +16,8 @@ from homeassistant.core import HomeAssistant
|
|||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
from homeassistant.helpers.trigger import PluggableAction
|
from homeassistant.helpers.trigger import PluggableAction
|
||||||
|
|
||||||
from . import LOGGER, PhilipsTVConfigEntry, PhilipsTVDataUpdateCoordinator
|
from . import LOGGER, PhilipsTVConfigEntry
|
||||||
|
from .coordinator import PhilipsTVDataUpdateCoordinator
|
||||||
from .entity import PhilipsJsEntity
|
from .entity import PhilipsJsEntity
|
||||||
from .helpers import async_get_turn_on_trigger
|
from .helpers import async_get_turn_on_trigger
|
||||||
|
|
||||||
|
@ -8,7 +8,8 @@ from homeassistant.components.switch import SwitchEntity
|
|||||||
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 . import PhilipsTVConfigEntry, PhilipsTVDataUpdateCoordinator
|
from . import PhilipsTVConfigEntry
|
||||||
|
from .coordinator import PhilipsTVDataUpdateCoordinator
|
||||||
from .entity import PhilipsJsEntity
|
from .entity import PhilipsJsEntity
|
||||||
|
|
||||||
HUE_POWER_OFF = "Off"
|
HUE_POWER_OFF = "Off"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user