Fix Panasonic Viera TV going unavailable when turned off (#53788)

This commit is contained in:
Alex Henry 2021-08-04 22:44:16 +12:00 committed by GitHub
parent fe957b74be
commit b77335d6f9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 82 additions and 17 deletions

View File

@ -1,7 +1,7 @@
"""The Panasonic Viera integration.""" """The Panasonic Viera integration."""
from functools import partial from functools import partial
import logging import logging
from urllib.request import URLError from urllib.request import HTTPError, URLError
from panasonic_viera import EncryptionRequired, Keys, RemoteControl, SOAPError from panasonic_viera import EncryptionRequired, Keys, RemoteControl, SOAPError
import voluptuous as vol import voluptuous as vol
@ -247,11 +247,13 @@ class Remote:
"The connection couldn't be encrypted. Please reconfigure your TV" "The connection couldn't be encrypted. Please reconfigure your TV"
) )
self.available = False self.available = False
except (SOAPError): except (SOAPError, HTTPError) as err:
_LOGGER.debug("An error occurred: %s", err)
self.state = STATE_OFF self.state = STATE_OFF
self.available = True self.available = True
await self.async_create_remote_control() await self.async_create_remote_control()
except (URLError, OSError): except (URLError, OSError) as err:
_LOGGER.debug("An error occurred: %s", err)
self.state = STATE_OFF self.state = STATE_OFF
self.available = self._on_action is not None self.available = self._on_action is not None
await self.async_create_remote_control() await self.async_create_remote_control()

View File

@ -17,8 +17,12 @@ from homeassistant.components.panasonic_viera.const import (
DEFAULT_MODEL_NUMBER, DEFAULT_MODEL_NUMBER,
DEFAULT_NAME, DEFAULT_NAME,
DEFAULT_PORT, DEFAULT_PORT,
DOMAIN,
) )
from homeassistant.const import CONF_HOST, CONF_NAME, CONF_PORT from homeassistant.const import CONF_HOST, CONF_NAME, CONF_PORT
from homeassistant.core import HomeAssistant
from tests.common import MockConfigEntry
MOCK_BASIC_DATA = { MOCK_BASIC_DATA = {
CONF_HOST: "0.0.0.0", CONF_HOST: "0.0.0.0",
@ -74,20 +78,11 @@ def get_mock_remote(
mock_remote.authorize_pin_code = authorize_pin_code mock_remote.authorize_pin_code = authorize_pin_code
def get_device_info(): mock_remote.get_device_info = Mock(return_value=device_info)
return device_info
mock_remote.get_device_info = get_device_info mock_remote.send_key = Mock()
def send_key(key): mock_remote.get_volume = Mock(return_value=100)
return
mock_remote.send_key = Mock(send_key)
def get_volume(key):
return 100
mock_remote.get_volume = Mock(get_volume)
return mock_remote return mock_remote
@ -102,3 +97,21 @@ def mock_remote_fixture():
return_value=mock_remote, return_value=mock_remote,
): ):
yield mock_remote yield mock_remote
@pytest.fixture
async def init_integration(hass: HomeAssistant, mock_remote: Mock) -> MockConfigEntry:
"""Set up the Panasonic Viera integration for testing."""
mock_entry = MockConfigEntry(
domain=DOMAIN,
unique_id=MOCK_DEVICE_INFO[ATTR_UDN],
data={**MOCK_CONFIG_DATA, **MOCK_ENCRYPTION_DATA, **MOCK_DEVICE_INFO},
)
mock_entry.add_to_hass(hass)
await hass.config_entries.async_setup(mock_entry.entry_id)
await hass.async_block_till_done()
return mock_entry

View File

@ -0,0 +1,47 @@
"""Test the Panasonic Viera media player entity."""
from datetime import timedelta
from unittest.mock import Mock
from urllib.error import HTTPError, URLError
from homeassistant.const import STATE_OFF, STATE_ON, STATE_UNAVAILABLE
from homeassistant.core import HomeAssistant
from homeassistant.util.dt import utcnow
from tests.common import MockConfigEntry, async_fire_time_changed
async def test_media_player_handle_URLerror(
hass: HomeAssistant, init_integration: MockConfigEntry, mock_remote: Mock
) -> None:
"""Test remote handle URLError as Unavailable."""
state_tv = hass.states.get("media_player.panasonic_viera_tv")
assert state_tv.state == STATE_ON
# simulate timeout error
mock_remote.get_mute = Mock(side_effect=URLError(None, None))
async_fire_time_changed(hass, utcnow() + timedelta(minutes=2))
await hass.async_block_till_done()
state_tv = hass.states.get("media_player.panasonic_viera_tv")
assert state_tv.state == STATE_UNAVAILABLE
async def test_media_player_handle_HTTPError(
hass: HomeAssistant, init_integration: MockConfigEntry, mock_remote: Mock
) -> None:
"""Test remote handle HTTPError as Off."""
state_tv = hass.states.get("media_player.panasonic_viera_tv")
assert state_tv.state == STATE_ON
# simulate http badrequest
mock_remote.get_mute = Mock(side_effect=HTTPError(None, 400, None, None, None))
async_fire_time_changed(hass, utcnow() + timedelta(minutes=2))
await hass.async_block_till_done()
state_tv = hass.states.get("media_player.panasonic_viera_tv")
assert state_tv.state == STATE_OFF

View File

@ -1,8 +1,8 @@
"""Test the Panasonic Viera remote entity.""" """Test the Panasonic Viera remote entity."""
from unittest.mock import call from unittest.mock import Mock, call
from panasonic_viera import Keys from panasonic_viera import Keys, SOAPError
from homeassistant.components.panasonic_viera.const import ATTR_UDN, DOMAIN from homeassistant.components.panasonic_viera.const import ATTR_UDN, DOMAIN
from homeassistant.components.remote import ( from homeassistant.components.remote import (
@ -38,6 +38,9 @@ async def test_onoff(hass, mock_remote):
data = {ATTR_ENTITY_ID: "remote.panasonic_viera_tv"} data = {ATTR_ENTITY_ID: "remote.panasonic_viera_tv"}
# simulate tv off when async_update
mock_remote.get_mute = Mock(side_effect=SOAPError)
await hass.services.async_call(REMOTE_DOMAIN, SERVICE_TURN_OFF, data) await hass.services.async_call(REMOTE_DOMAIN, SERVICE_TURN_OFF, data)
await hass.services.async_call(REMOTE_DOMAIN, SERVICE_TURN_ON, data) await hass.services.async_call(REMOTE_DOMAIN, SERVICE_TURN_ON, data)
await hass.async_block_till_done() await hass.async_block_till_done()