mirror of
https://github.com/home-assistant/core.git
synced 2025-07-28 07:37:34 +00:00
Rework Onkyo discovery and interview (#120668)
* Rework Onkyo discovery and interview * Move class outside setup function * Revert changing default name * Rename to volume resolution
This commit is contained in:
parent
4e7e896601
commit
e6c61f207d
@ -3,6 +3,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
from dataclasses import dataclass
|
||||
import logging
|
||||
from typing import Any
|
||||
|
||||
@ -137,6 +138,16 @@ ONKYO_SELECT_OUTPUT_SCHEMA = vol.Schema(
|
||||
SERVICE_SELECT_HDMI_OUTPUT = "onkyo_select_hdmi_output"
|
||||
|
||||
|
||||
@dataclass
|
||||
class ReceiverInfo:
|
||||
"""Onkyo Receiver information."""
|
||||
|
||||
host: str
|
||||
port: int
|
||||
model_name: str
|
||||
identifier: str
|
||||
|
||||
|
||||
async def async_setup_platform(
|
||||
hass: HomeAssistant,
|
||||
config: ConfigType,
|
||||
@ -169,16 +180,23 @@ async def async_setup_platform(
|
||||
)
|
||||
|
||||
host = config.get(CONF_HOST)
|
||||
name = config[CONF_NAME]
|
||||
name = config.get(CONF_NAME)
|
||||
max_volume = config[CONF_MAX_VOLUME]
|
||||
receiver_max_volume = config[CONF_RECEIVER_MAX_VOLUME]
|
||||
sources = config[CONF_SOURCES]
|
||||
|
||||
async def async_setup_receiver(
|
||||
info: ReceiverInfo, discovered: bool, name: str | None
|
||||
) -> None:
|
||||
@callback
|
||||
def async_onkyo_update_callback(message: tuple[str, str, Any], origin: str) -> None:
|
||||
def async_onkyo_update_callback(
|
||||
message: tuple[str, str, Any], origin: str
|
||||
) -> None:
|
||||
"""Process new message from receiver."""
|
||||
receiver = receivers[origin]
|
||||
_LOGGER.debug("Received update callback from %s: %s", receiver.name, message)
|
||||
_LOGGER.debug(
|
||||
"Received update callback from %s: %s", receiver.name, message
|
||||
)
|
||||
|
||||
zone, _, value = message
|
||||
entity = entities[origin].get(zone)
|
||||
@ -199,13 +217,25 @@ async def async_setup_platform(
|
||||
def async_onkyo_connect_callback(origin: str) -> None:
|
||||
"""Receiver (re)connected."""
|
||||
receiver = receivers[origin]
|
||||
_LOGGER.debug("Receiver (re)connected: %s (%s)", receiver.name, receiver.host)
|
||||
_LOGGER.debug(
|
||||
"Receiver (re)connected: %s (%s)", receiver.name, receiver.host
|
||||
)
|
||||
|
||||
for entity in entities[origin].values():
|
||||
entity.backfill_state()
|
||||
|
||||
def setup_receiver(receiver: pyeiscp.Connection) -> None:
|
||||
KNOWN_HOSTS.append(receiver.host)
|
||||
_LOGGER.debug("Creating receiver: %s (%s)", info.model_name, info.host)
|
||||
receiver = await pyeiscp.Connection.create(
|
||||
host=info.host,
|
||||
port=info.port,
|
||||
update_callback=async_onkyo_update_callback,
|
||||
connect_callback=async_onkyo_connect_callback,
|
||||
)
|
||||
|
||||
receiver.model_name = info.model_name
|
||||
receiver.identifier = info.identifier
|
||||
receiver.name = name or info.model_name
|
||||
receiver.discovered = discovered
|
||||
|
||||
# Store the receiver object and create a dictionary to store its entities.
|
||||
receivers[receiver.host] = receiver
|
||||
@ -224,34 +254,38 @@ async def async_setup_platform(
|
||||
entities[receiver.host]["main"] = main_entity
|
||||
async_add_entities([main_entity])
|
||||
|
||||
if host is not None and host not in KNOWN_HOSTS:
|
||||
if host is not None:
|
||||
if host in KNOWN_HOSTS:
|
||||
return
|
||||
|
||||
_LOGGER.debug("Manually creating receiver: %s (%s)", name, host)
|
||||
receiver = await pyeiscp.Connection.create(
|
||||
host=host,
|
||||
update_callback=async_onkyo_update_callback,
|
||||
connect_callback=async_onkyo_connect_callback,
|
||||
)
|
||||
|
||||
# The library automatically adds a name and identifier only on discovered hosts,
|
||||
# so manually add them here instead.
|
||||
receiver.name = name
|
||||
receiver.identifier = None
|
||||
|
||||
setup_receiver(receiver)
|
||||
else:
|
||||
|
||||
@callback
|
||||
async def async_onkyo_discovery_callback(receiver: pyeiscp.Connection):
|
||||
"""Receiver discovered, connection not yet active."""
|
||||
_LOGGER.debug("Receiver discovered: %s (%s)", receiver.name, receiver.host)
|
||||
if receiver.host not in KNOWN_HOSTS:
|
||||
await receiver.connect()
|
||||
setup_receiver(receiver)
|
||||
async def async_onkyo_interview_callback(conn: pyeiscp.Connection):
|
||||
"""Receiver interviewed, connection not yet active."""
|
||||
info = ReceiverInfo(conn.host, conn.port, conn.name, conn.identifier)
|
||||
_LOGGER.debug("Receiver interviewed: %s (%s)", info.model_name, info.host)
|
||||
if info.host not in KNOWN_HOSTS:
|
||||
KNOWN_HOSTS.append(info.host)
|
||||
await async_setup_receiver(info, False, name)
|
||||
|
||||
await pyeiscp.Connection.discover(
|
||||
host=host,
|
||||
discovery_callback=async_onkyo_interview_callback,
|
||||
)
|
||||
else:
|
||||
_LOGGER.debug("Discovering receivers")
|
||||
|
||||
@callback
|
||||
async def async_onkyo_discovery_callback(conn: pyeiscp.Connection):
|
||||
"""Receiver discovered, connection not yet active."""
|
||||
info = ReceiverInfo(conn.host, conn.port, conn.name, conn.identifier)
|
||||
_LOGGER.debug("Receiver discovered: %s (%s)", info.model_name, info.host)
|
||||
if info.host not in KNOWN_HOSTS:
|
||||
KNOWN_HOSTS.append(info.host)
|
||||
await async_setup_receiver(info, True, None)
|
||||
|
||||
_LOGGER.debug("Discovering receivers")
|
||||
await pyeiscp.Connection.discover(
|
||||
update_callback=async_onkyo_update_callback,
|
||||
connect_callback=async_onkyo_connect_callback,
|
||||
discovery_callback=async_onkyo_discovery_callback,
|
||||
)
|
||||
|
||||
@ -279,29 +313,27 @@ class OnkyoMediaPlayer(MediaPlayerEntity):
|
||||
sources: dict[str, str],
|
||||
zone: str,
|
||||
max_volume: int,
|
||||
receiver_max_volume: int,
|
||||
volume_resolution: int,
|
||||
) -> None:
|
||||
"""Initialize the Onkyo Receiver."""
|
||||
self._receiver = receiver
|
||||
name = receiver.name
|
||||
self._attr_name = f"{name}{' ' + ZONES[zone] if zone != 'main' else ''}"
|
||||
identifier = receiver.identifier
|
||||
if identifier is not None:
|
||||
# discovered
|
||||
self._attr_name = f"{name}{' ' + ZONES[zone] if zone != 'main' else ''}"
|
||||
if receiver.discovered:
|
||||
if zone == "main":
|
||||
# keep legacy unique_id
|
||||
self._attr_unique_id = f"{name}_{identifier}"
|
||||
else:
|
||||
self._attr_unique_id = f"{identifier}_{zone}"
|
||||
else:
|
||||
# not discovered
|
||||
self._attr_unique_id = None
|
||||
|
||||
self._zone = zone
|
||||
self._source_mapping = sources
|
||||
self._reverse_mapping = {value: key for key, value in sources.items()}
|
||||
self._max_volume = max_volume
|
||||
self._receiver_max_volume = receiver_max_volume
|
||||
self._volume_resolution = volume_resolution
|
||||
|
||||
self._attr_source_list = list(sources.values())
|
||||
self._attr_extra_state_attributes = {}
|
||||
@ -350,9 +382,9 @@ class OnkyoMediaPlayer(MediaPlayerEntity):
|
||||
will give 80% volume on the receiver. Then we convert that to the correct
|
||||
scale for the receiver.
|
||||
"""
|
||||
# HA_VOL * (MAX VOL / 100) * MAX_RECEIVER_VOL
|
||||
# HA_VOL * (MAX VOL / 100) * VOL_RESOLUTION
|
||||
self._update_receiver(
|
||||
"volume", int(volume * (self._max_volume / 100) * self._receiver_max_volume)
|
||||
"volume", int(volume * (self._max_volume / 100) * self._volume_resolution)
|
||||
)
|
||||
|
||||
async def async_volume_up(self) -> None:
|
||||
@ -430,9 +462,9 @@ class OnkyoMediaPlayer(MediaPlayerEntity):
|
||||
self._attr_extra_state_attributes.pop(ATTR_VIDEO_OUT, None)
|
||||
elif command in ["volume", "master-volume"] and value != "N/A":
|
||||
self._supports_volume = True
|
||||
# AMP_VOL / (MAX_RECEIVER_VOL * (MAX_VOL / 100))
|
||||
# AMP_VOL / (VOL_RESOLUTION * (MAX_VOL / 100))
|
||||
self._attr_volume_level = value / (
|
||||
self._receiver_max_volume * self._max_volume / 100
|
||||
self._volume_resolution * self._max_volume / 100
|
||||
)
|
||||
elif command in ["muting", "audio-muting"]:
|
||||
self._attr_is_volume_muted = bool(value == "on")
|
||||
|
Loading…
x
Reference in New Issue
Block a user