mirror of
https://github.com/home-assistant/core.git
synced 2025-07-16 01:37:08 +00:00
Fix status update loop in bluesound integration (#123790)
* Fix retry loop for status update * Use 'available' instead of _is_online * Fix tests
This commit is contained in:
parent
193a7b7360
commit
30994710e6
@ -244,7 +244,6 @@ class BluesoundPlayer(MediaPlayerEntity):
|
|||||||
self._status: Status | None = None
|
self._status: Status | None = None
|
||||||
self._inputs: list[Input] = []
|
self._inputs: list[Input] = []
|
||||||
self._presets: list[Preset] = []
|
self._presets: list[Preset] = []
|
||||||
self._is_online = False
|
|
||||||
self._muted = False
|
self._muted = False
|
||||||
self._master: BluesoundPlayer | None = None
|
self._master: BluesoundPlayer | None = None
|
||||||
self._is_master = False
|
self._is_master = False
|
||||||
@ -312,20 +311,24 @@ class BluesoundPlayer(MediaPlayerEntity):
|
|||||||
|
|
||||||
async def _start_poll_command(self):
|
async def _start_poll_command(self):
|
||||||
"""Loop which polls the status of the player."""
|
"""Loop which polls the status of the player."""
|
||||||
try:
|
while True:
|
||||||
while True:
|
try:
|
||||||
await self.async_update_status()
|
await self.async_update_status()
|
||||||
|
except (TimeoutError, ClientError):
|
||||||
except (TimeoutError, ClientError):
|
_LOGGER.error(
|
||||||
_LOGGER.error("Node %s:%s is offline, retrying later", self.host, self.port)
|
"Node %s:%s is offline, retrying later", self.host, self.port
|
||||||
await asyncio.sleep(NODE_OFFLINE_CHECK_TIMEOUT)
|
)
|
||||||
self.start_polling()
|
await asyncio.sleep(NODE_OFFLINE_CHECK_TIMEOUT)
|
||||||
|
except CancelledError:
|
||||||
except CancelledError:
|
_LOGGER.debug(
|
||||||
_LOGGER.debug("Stopping the polling of node %s:%s", self.host, self.port)
|
"Stopping the polling of node %s:%s", self.host, self.port
|
||||||
except Exception:
|
)
|
||||||
_LOGGER.exception("Unexpected error in %s:%s", self.host, self.port)
|
return
|
||||||
raise
|
except Exception:
|
||||||
|
_LOGGER.exception(
|
||||||
|
"Unexpected error in %s:%s, retrying later", self.host, self.port
|
||||||
|
)
|
||||||
|
await asyncio.sleep(NODE_OFFLINE_CHECK_TIMEOUT)
|
||||||
|
|
||||||
async def async_added_to_hass(self) -> None:
|
async def async_added_to_hass(self) -> None:
|
||||||
"""Start the polling task."""
|
"""Start the polling task."""
|
||||||
@ -348,7 +351,7 @@ class BluesoundPlayer(MediaPlayerEntity):
|
|||||||
|
|
||||||
async def async_update(self) -> None:
|
async def async_update(self) -> None:
|
||||||
"""Update internal status of the entity."""
|
"""Update internal status of the entity."""
|
||||||
if not self._is_online:
|
if not self.available:
|
||||||
return
|
return
|
||||||
|
|
||||||
with suppress(TimeoutError):
|
with suppress(TimeoutError):
|
||||||
@ -365,7 +368,7 @@ class BluesoundPlayer(MediaPlayerEntity):
|
|||||||
try:
|
try:
|
||||||
status = await self._player.status(etag=etag, poll_timeout=120, timeout=125)
|
status = await self._player.status(etag=etag, poll_timeout=120, timeout=125)
|
||||||
|
|
||||||
self._is_online = True
|
self._attr_available = True
|
||||||
self._last_status_update = dt_util.utcnow()
|
self._last_status_update = dt_util.utcnow()
|
||||||
self._status = status
|
self._status = status
|
||||||
|
|
||||||
@ -394,7 +397,7 @@ class BluesoundPlayer(MediaPlayerEntity):
|
|||||||
|
|
||||||
self.async_write_ha_state()
|
self.async_write_ha_state()
|
||||||
except (TimeoutError, ClientError):
|
except (TimeoutError, ClientError):
|
||||||
self._is_online = False
|
self._attr_available = False
|
||||||
self._last_status_update = None
|
self._last_status_update = None
|
||||||
self._status = None
|
self._status = None
|
||||||
self.async_write_ha_state()
|
self.async_write_ha_state()
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
from collections.abc import Generator
|
from collections.abc import Generator
|
||||||
from unittest.mock import AsyncMock, patch
|
from unittest.mock import AsyncMock, patch
|
||||||
|
|
||||||
from pyblu import SyncStatus
|
from pyblu import Status, SyncStatus
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from homeassistant.components.bluesound.const import DOMAIN
|
from homeassistant.components.bluesound.const import DOMAIN
|
||||||
@ -39,6 +39,35 @@ def sync_status() -> SyncStatus:
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def status() -> Status:
|
||||||
|
"""Return a status object."""
|
||||||
|
return Status(
|
||||||
|
etag="etag",
|
||||||
|
input_id=None,
|
||||||
|
service=None,
|
||||||
|
state="playing",
|
||||||
|
shuffle=False,
|
||||||
|
album=None,
|
||||||
|
artist=None,
|
||||||
|
name=None,
|
||||||
|
image=None,
|
||||||
|
volume=10,
|
||||||
|
volume_db=22.3,
|
||||||
|
mute=False,
|
||||||
|
mute_volume=None,
|
||||||
|
mute_volume_db=None,
|
||||||
|
seconds=2,
|
||||||
|
total_seconds=123.1,
|
||||||
|
can_seek=False,
|
||||||
|
sleep=0,
|
||||||
|
group_name=None,
|
||||||
|
group_volume=None,
|
||||||
|
indexing=False,
|
||||||
|
stream_url=None,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def mock_setup_entry() -> Generator[AsyncMock]:
|
def mock_setup_entry() -> Generator[AsyncMock]:
|
||||||
"""Override async_setup_entry."""
|
"""Override async_setup_entry."""
|
||||||
@ -65,7 +94,7 @@ def mock_config_entry(hass: HomeAssistant) -> MockConfigEntry:
|
|||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def mock_player() -> Generator[AsyncMock]:
|
def mock_player(status: Status) -> Generator[AsyncMock]:
|
||||||
"""Mock the player."""
|
"""Mock the player."""
|
||||||
with (
|
with (
|
||||||
patch(
|
patch(
|
||||||
@ -78,7 +107,7 @@ def mock_player() -> Generator[AsyncMock]:
|
|||||||
):
|
):
|
||||||
player = mock_player.return_value
|
player = mock_player.return_value
|
||||||
player.__aenter__.return_value = player
|
player.__aenter__.return_value = player
|
||||||
player.status.return_value = None
|
player.status.return_value = status
|
||||||
player.sync_status.return_value = SyncStatus(
|
player.sync_status.return_value = SyncStatus(
|
||||||
etag="etag",
|
etag="etag",
|
||||||
id="1.1.1.1:11000",
|
id="1.1.1.1:11000",
|
||||||
|
@ -41,7 +41,7 @@ async def test_user_flow_success(
|
|||||||
|
|
||||||
|
|
||||||
async def test_user_flow_cannot_connect(
|
async def test_user_flow_cannot_connect(
|
||||||
hass: HomeAssistant, mock_player: AsyncMock
|
hass: HomeAssistant, mock_player: AsyncMock, mock_setup_entry: AsyncMock
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test we handle cannot connect error."""
|
"""Test we handle cannot connect error."""
|
||||||
result = await hass.config_entries.flow.async_init(
|
result = await hass.config_entries.flow.async_init(
|
||||||
@ -76,6 +76,8 @@ async def test_user_flow_cannot_connect(
|
|||||||
CONF_PORT: 11000,
|
CONF_PORT: 11000,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mock_setup_entry.assert_called_once()
|
||||||
|
|
||||||
|
|
||||||
async def test_user_flow_aleady_configured(
|
async def test_user_flow_aleady_configured(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user