Skip to content

Commit c0365df

Browse files
authored
Query state after turn on in Onkyo (home-assistant#158093)
1 parent 02aa3fc commit c0365df

File tree

2 files changed

+103
-26
lines changed

2 files changed

+103
-26
lines changed

homeassistant/components/onkyo/media_player.py

Lines changed: 40 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,8 @@
6060
ATTR_VIDEO_INFORMATION = "video_information"
6161
ATTR_VIDEO_OUT = "video_out"
6262

63-
AUDIO_VIDEO_INFORMATION_UPDATE_WAIT_TIME = 8
63+
QUERY_STATE_DELAY = 4
64+
QUERY_AV_INFO_DELAY = 8
6465

6566
AUDIO_INFORMATION_MAPPING = [
6667
"audio_input_port",
@@ -112,7 +113,7 @@ async def connect_callback(reconnect: bool) -> None:
112113
if reconnect:
113114
for entity in entities.values():
114115
if entity.enabled:
115-
await entity.backfill_state()
116+
await entity.query_state()
116117

117118
async def update_callback(message: Status) -> None:
118119
if isinstance(message, status.Raw):
@@ -160,7 +161,8 @@ class OnkyoMediaPlayer(MediaPlayerEntity):
160161
_supports_audio_info: bool = False
161162
_supports_video_info: bool = False
162163

163-
_query_task: asyncio.Task | None = None
164+
_query_state_task: asyncio.Task | None = None
165+
_query_av_info_task: asyncio.Task | None = None
164166

165167
def __init__(
166168
self,
@@ -220,20 +222,19 @@ def __init__(
220222

221223
async def async_added_to_hass(self) -> None:
222224
"""Entity has been added to hass."""
223-
await self.backfill_state()
225+
await self.query_state()
224226

225227
async def async_will_remove_from_hass(self) -> None:
226-
"""Cancel the query timer when the entity is removed."""
227-
if self._query_task:
228-
self._query_task.cancel()
229-
self._query_task = None
230-
231-
async def backfill_state(self) -> None:
232-
"""Get the receiver to send all the info we care about.
233-
234-
Usually run only on connect, as we can otherwise rely on the
235-
receiver to keep us informed of changes.
236-
"""
228+
"""Cancel the tasks when the entity is removed."""
229+
if self._query_state_task is not None:
230+
self._query_state_task.cancel()
231+
self._query_state_task = None
232+
if self._query_av_info_task is not None:
233+
self._query_av_info_task.cancel()
234+
self._query_av_info_task = None
235+
236+
async def query_state(self) -> None:
237+
"""Query the receiver for all the info, that we care about."""
237238
await self._manager.write(query.Power(self._zone))
238239
await self._manager.write(query.Volume(self._zone))
239240
await self._manager.write(query.Muting(self._zone))
@@ -342,6 +343,8 @@ def process_update(self, message: status.Known) -> None:
342343
"""Process update."""
343344
match message:
344345
case status.Power(param=status.Power.Param.ON):
346+
if self.state != MediaPlayerState.ON:
347+
self._query_state_delayed()
345348
self._attr_state = MediaPlayerState.ON
346349
case status.Power(param=status.Power.Param.STANDBY):
347350
self._attr_state = MediaPlayerState.OFF
@@ -437,15 +440,28 @@ def process_update(self, message: status.Known) -> None:
437440

438441
self.async_write_ha_state()
439442

443+
def _query_state_delayed(self) -> None:
444+
if self._query_state_task is not None:
445+
self._query_state_task.cancel()
446+
self._query_state_task = None
447+
448+
async def coro() -> None:
449+
await asyncio.sleep(QUERY_STATE_DELAY)
450+
await self.query_state()
451+
self._query_state_task = None
452+
453+
self._query_state_task = asyncio.create_task(coro())
454+
440455
def _query_av_info_delayed(self) -> None:
441-
if self._zone == Zone.MAIN and not self._query_task:
456+
if self._zone is not Zone.MAIN or self._query_av_info_task is not None:
457+
return
442458

443-
async def _query_av_info() -> None:
444-
await asyncio.sleep(AUDIO_VIDEO_INFORMATION_UPDATE_WAIT_TIME)
445-
if self._supports_audio_info:
446-
await self._manager.write(query.AudioInformation())
447-
if self._supports_video_info:
448-
await self._manager.write(query.VideoInformation())
449-
self._query_task = None
459+
async def coro() -> None:
460+
await asyncio.sleep(QUERY_AV_INFO_DELAY)
461+
if self._supports_audio_info:
462+
await self._manager.write(query.AudioInformation())
463+
if self._supports_video_info:
464+
await self._manager.write(query.VideoInformation())
465+
self._query_av_info_task = None
450466

451-
self._query_task = asyncio.create_task(_query_av_info())
467+
self._query_av_info_task = asyncio.create_task(coro())

tests/components/onkyo/test_media_player.py

Lines changed: 63 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
"""Test Onkyo media player platform."""
22

3+
import asyncio
34
from collections.abc import AsyncGenerator
45
from unittest.mock import AsyncMock, patch
56

6-
from aioonkyo import Instruction, Zone, command
7+
from aioonkyo import Code, Instruction, Kind, Zone, command, query, status
78
import pytest
89
from syrupy.assertion import SnapshotAssertion
910

@@ -56,7 +57,11 @@ async def auto_setup_integration(
5657
"""Auto setup integration."""
5758
with (
5859
patch(
59-
"homeassistant.components.onkyo.media_player.AUDIO_VIDEO_INFORMATION_UPDATE_WAIT_TIME",
60+
"homeassistant.components.onkyo.media_player.QUERY_AV_INFO_DELAY",
61+
0,
62+
),
63+
patch(
64+
"homeassistant.components.onkyo.media_player.QUERY_STATE_DELAY",
6065
0,
6166
),
6267
patch("homeassistant.components.onkyo.PLATFORMS", [Platform.MEDIA_PLAYER]),
@@ -228,3 +233,59 @@ async def test_select_hdmi_output(
228233
blocking=True,
229234
)
230235
assert writes[0] == command.HDMIOutput(command.HDMIOutput.Param.BOTH)
236+
237+
238+
async def test_query_state_task(
239+
read_queue: asyncio.Queue, writes: list[Instruction]
240+
) -> None:
241+
"""Test query state task."""
242+
read_queue.put_nowait(
243+
status.Power(
244+
Code.from_kind_zone(Kind.POWER, Zone.MAIN), None, status.Power.Param.STANDBY
245+
)
246+
)
247+
read_queue.put_nowait(
248+
status.Power(
249+
Code.from_kind_zone(Kind.POWER, Zone.MAIN), None, status.Power.Param.ON
250+
)
251+
)
252+
read_queue.put_nowait(
253+
status.Power(
254+
Code.from_kind_zone(Kind.POWER, Zone.MAIN), None, status.Power.Param.STANDBY
255+
)
256+
)
257+
read_queue.put_nowait(
258+
status.Power(
259+
Code.from_kind_zone(Kind.POWER, Zone.MAIN), None, status.Power.Param.ON
260+
)
261+
)
262+
263+
await asyncio.sleep(0.1)
264+
265+
queries = [w for w in writes if isinstance(w, query.Volume)]
266+
assert len(queries) == 1
267+
268+
269+
async def test_query_av_info_task(
270+
read_queue: asyncio.Queue, writes: list[Instruction]
271+
) -> None:
272+
"""Test query AV info task."""
273+
read_queue.put_nowait(
274+
status.InputSource(
275+
Code.from_kind_zone(Kind.INPUT_SOURCE, Zone.MAIN),
276+
None,
277+
status.InputSource.Param("24"),
278+
)
279+
)
280+
read_queue.put_nowait(
281+
status.InputSource(
282+
Code.from_kind_zone(Kind.INPUT_SOURCE, Zone.MAIN),
283+
None,
284+
status.InputSource.Param("00"),
285+
)
286+
)
287+
288+
await asyncio.sleep(0.1)
289+
290+
queries = [w for w in writes if isinstance(w, query.AudioInformation)]
291+
assert len(queries) == 1

0 commit comments

Comments
 (0)