-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Rewrote the component to have config flow and 1 instance instead of 2
- Loading branch information
Showing
22 changed files
with
640 additions
and
310 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
"""The panasonic_bluray remote and media player component.""" | ||
from __future__ import absolute_import | ||
|
||
from panacotta import PanasonicBD | ||
from .const import DOMAIN, DEFAULT_DEVICE_NAME, PANASONIC_COORDINATOR, STARTUP, PANASONIC_API, NAME | ||
import logging | ||
from homeassistant.config_entries import ConfigEntry | ||
from homeassistant.const import Platform, CONF_HOST | ||
from homeassistant.core import HomeAssistant | ||
from .coordinator import PanasonicCoordinator | ||
|
||
_LOGGER: logging.Logger = logging.getLogger(__package__) | ||
_LOGGER.info(STARTUP) | ||
|
||
|
||
PLATFORMS: list[Platform] = [ | ||
Platform.MEDIA_PLAYER, | ||
Platform.REMOTE | ||
] | ||
|
||
|
||
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: | ||
"""Set up Unfolded Circle Remote from a config entry.""" | ||
|
||
panasonic_device = PanasonicBD(entry.data[CONF_HOST]) | ||
_LOGGER.debug("Panasonic device initialization") | ||
coordinator = PanasonicCoordinator(hass, panasonic_device, DEFAULT_DEVICE_NAME) | ||
hass.data.setdefault(DOMAIN, {})[entry.entry_id] = { | ||
PANASONIC_COORDINATOR: coordinator, | ||
PANASONIC_API: panasonic_device, | ||
} | ||
|
||
# Retrieve info from Remote | ||
# Get Basic Device Information | ||
await coordinator.async_config_entry_first_refresh() | ||
|
||
await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS) | ||
entry.async_on_unload(entry.add_update_listener(update_listener)) | ||
# await zeroconf.async_get_async_instance(hass) | ||
return True | ||
|
||
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: | ||
"""Unload a config entry.""" | ||
try: | ||
coordinator: PanasonicCoordinator = hass.data[DOMAIN][entry.entry_id][PANASONIC_COORDINATOR] | ||
# coordinator.api.? | ||
except Exception as ex: | ||
_LOGGER.error("Sony device async_unload_entry error", ex) | ||
if unload_ok := await hass.config_entries.async_unload_platforms(entry, PLATFORMS): | ||
hass.data[DOMAIN].pop(entry.entry_id) | ||
return unload_ok | ||
|
||
|
||
async def update_listener(hass: HomeAssistant, entry: ConfigEntry): | ||
"""Update Listener.""" | ||
#TODO Should be ? | ||
#await async_unload_entry(hass, entry) | ||
#await async_setup_entry(hass, entry) | ||
await hass.config_entries.async_reload(entry.entry_id) | ||
|
||
|
||
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: | ||
"""Unload a config entry.""" | ||
try: | ||
coordinator: PanasonicCoordinator = hass.data[DOMAIN][entry.entry_id][PANASONIC_COORDINATOR] | ||
# coordinator.api.? | ||
except Exception as ex: | ||
_LOGGER.error("Panasonic device async_unload_entry error", ex) | ||
if unload_ok := await hass.config_entries.async_unload_platforms(entry, PLATFORMS): | ||
hass.data[DOMAIN].pop(entry.entry_id) | ||
return unload_ok | ||
|
||
|
||
async def update_listener(hass: HomeAssistant, entry: ConfigEntry): | ||
"""Update Listener.""" | ||
# TODO Should be ? | ||
# await async_unload_entry(hass, entry) | ||
# await async_setup_entry(hass, entry) | ||
await hass.config_entries.async_reload(entry.entry_id) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
"""Config flow for Unfolded Circle Remote integration.""" | ||
|
||
import logging | ||
from typing import Any | ||
|
||
import voluptuous as vol | ||
from homeassistant import config_entries | ||
from homeassistant.config_entries import ConfigEntry, ConfigFlow, OptionsFlow | ||
from homeassistant.const import CONF_HOST | ||
from homeassistant.data_entry_flow import FlowResult | ||
from homeassistant.exceptions import HomeAssistantError | ||
from panacotta import PanasonicBD | ||
|
||
from .const import DOMAIN, DEFAULT_DEVICE_NAME | ||
|
||
_LOGGER = logging.getLogger(__name__) | ||
|
||
STEP_USER_DATA_SCHEMA = vol.Schema({vol.Required(CONF_HOST): str}) | ||
|
||
def validate_input(user_input: dict[str, Any]) -> dict[str, Any]: | ||
"""Validate the user input allows us to connect. | ||
Data has the keys from STEP_USER_DATA_SCHEMA with values provided by the user. | ||
""" | ||
config = {} | ||
_LOGGER.debug("Sony device user input %s", user_input) | ||
panasonic_device = PanasonicBD(user_input[CONF_HOST]) | ||
state = panasonic_device.get_status() | ||
if state[0] == "error": | ||
config = {"error": f"Could not connect to Panasonic device with {user_input[CONF_HOST]}"} | ||
_LOGGER.error("Could not connect to Panasonic device with %s", user_input[CONF_HOST]) | ||
|
||
config.update(user_input) | ||
return config | ||
|
||
|
||
class PanasonicConfigFlow(ConfigFlow, domain=DOMAIN): | ||
"""Handle a config flow for Panasonic.""" | ||
|
||
VERSION = 1 | ||
MINOR_VERSION = 1 | ||
CONNECTION_CLASS = config_entries.CONN_CLASS_LOCAL_POLL | ||
|
||
reauth_entry: ConfigEntry | None = None | ||
user_input: dict[str, Any] | None = None | ||
|
||
def __init__(self) -> None: | ||
"""Sony Config Flow.""" | ||
self.discovery_info: dict[str, Any] = {} | ||
|
||
async def async_step_user( | ||
self, user_input: dict[str, Any] | None = None | ||
) -> FlowResult: | ||
"""Handle the initial step.""" | ||
errors: dict[str, str] = {} | ||
if user_input is None or user_input == {}: | ||
return self.async_show_form( | ||
step_id="user", data_schema=STEP_USER_DATA_SCHEMA, errors=errors | ||
) | ||
|
||
if self.user_input is None: | ||
self.user_input = user_input | ||
else: | ||
self.user_input.update(user_input) | ||
|
||
try: | ||
info = await self.hass.async_add_executor_job(validate_input, self.user_input) | ||
if info.get("error"): | ||
errors["base"] = "cannot_connect" | ||
return self.async_show_form( | ||
step_id="user", data_schema=STEP_USER_DATA_SCHEMA, errors=errors, | ||
) | ||
except Exception: # pylint: disable=broad-except | ||
_LOGGER.exception("Unexpected exception") | ||
errors["base"] = "unknown" | ||
else: | ||
if len(errors.keys()) == 0: | ||
await self.async_set_unique_id(self.user_input[CONF_HOST]) | ||
self._abort_if_unique_id_configured() | ||
|
||
return self.async_create_entry(title=DEFAULT_DEVICE_NAME, data=info) | ||
|
||
return self.async_show_form( | ||
step_id="user", data_schema=STEP_USER_DATA_SCHEMA, errors=errors | ||
) | ||
|
||
|
||
class PanasonicDeviceOptionsFlowHandler(OptionsFlow): | ||
"""Handle Panasonic options.""" | ||
|
||
def __init__(self, config_entry: ConfigEntry) -> None: | ||
"""Initialize options flow.""" | ||
self.config_entry = config_entry | ||
|
||
async def async_step_init( | ||
self, user_input: dict[str, int] | None = None | ||
) -> FlowResult: | ||
"""Manage Unfolded Circle options.""" | ||
if user_input is not None: | ||
return self.async_create_entry(title="", data=user_input) | ||
|
||
return self.async_show_form( | ||
step_id="init", | ||
data_schema=STEP_USER_DATA_SCHEMA, | ||
) | ||
|
||
|
||
class CannotConnect(HomeAssistantError): | ||
"""Error to indicate we cannot connect.""" | ||
|
||
|
||
class InvalidAuth(HomeAssistantError): | ||
"""Error to indicate there is invalid auth.""" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
"""The IntelliFire integration.""" | ||
from __future__ import annotations | ||
|
||
import logging | ||
from typing import Any | ||
|
||
import requests | ||
from homeassistant.components.media_player import MediaPlayerState | ||
from homeassistant.core import HomeAssistant | ||
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed | ||
from homeassistant.util import utcnow | ||
from panacotta import PanasonicBD | ||
|
||
from .const import MIN_TIME_BETWEEN_SCANS, DOMAIN | ||
|
||
_LOGGER = logging.getLogger(__name__) | ||
|
||
|
||
class PanasonicCoordinator(DataUpdateCoordinator[dict[str, Any]]): | ||
"""Data update coordinator for an Unfolded Circle Remote device.""" | ||
# List of events to subscribe to the websocket | ||
subscribe_events: dict[str, bool] | ||
|
||
def __init__(self, hass: HomeAssistant, panasonic_device: PanasonicBD, name: str) -> None: | ||
"""Initialize the Coordinator.""" | ||
super().__init__( | ||
hass, | ||
name=DOMAIN, | ||
logger=_LOGGER, | ||
update_interval=MIN_TIME_BETWEEN_SCANS, | ||
) | ||
self.hass = hass | ||
self.name = name | ||
self.api = panasonic_device | ||
self.data = {} | ||
|
||
async def _async_update_data(self) -> dict[str, Any]: | ||
"""Get the latest data from the Unfolded Circle Remote.""" | ||
_LOGGER.debug("Sony device coordinator update") | ||
try: | ||
self.data = await self.hass.async_add_executor_job(self.update) | ||
return self.data | ||
except Exception as ex: | ||
_LOGGER.error("Sony device coordinator error during update", ex) | ||
raise UpdateFailed( | ||
f"Error communicating with Sony device API {ex}" | ||
) from ex | ||
|
||
def update(self) -> dict[str, any]: | ||
"""Update the internal state by querying the device.""" | ||
data = {} | ||
# This can take 5+ seconds to complete | ||
state = self.api.get_play_status() | ||
|
||
if state[0] == "error": | ||
data["state"] = None | ||
elif state[0] in ["off", "standby"]: | ||
# We map both of these to off. If it's really off we can't | ||
# turn it on, but from standby we can go to idle by pressing | ||
# POWER. | ||
data["state"] = MediaPlayerState.OFF | ||
elif state[0] in ["paused", "stopped"]: | ||
data["state"] = MediaPlayerState.IDLE | ||
elif state[0] == "playing": | ||
data["state"] = MediaPlayerState.PLAYING | ||
|
||
# Update our current media position + length | ||
if state[1] >= 0: | ||
data["media_position"] = state[1] | ||
else: | ||
data["media_position"] = 0 | ||
data["media_position_updated_at"] = utcnow() | ||
data["media_duration"] = state[2] | ||
return data | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
{ | ||
"domain": "panasonic_bluray", | ||
"name": "Panasonic Blu-Ray", | ||
"config_flow": true, | ||
"documentation": "https://github.com/albaintor/panasonic_bluray_remote", | ||
"codeowners": ["@albaintor"], | ||
"iot_class": "local_polling", | ||
"integration_type": "device", | ||
"loggers": ["panacotta"], | ||
"version": "1.0.0", | ||
"requirements": ["panacotta==0.2"], | ||
"ssdp": [], | ||
"zeroconf": [] | ||
} |
Oops, something went wrong.