Fix Monoprice robustness (#33869)

* Silently handle update failures

* Limite parallel updates

* Remove return values

* Remove trailing return

* Add test for empty update
This commit is contained in:
On Freund 2020-04-09 18:04:12 +03:00 committed by GitHub
parent 90f7cd2d44
commit a4c9446b8d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 64 additions and 3 deletions

View file

@ -1,6 +1,8 @@
"""Support for interfacing with Monoprice 6 zone home audio controller.""" """Support for interfacing with Monoprice 6 zone home audio controller."""
import logging import logging
from serial import SerialException
from homeassistant import core from homeassistant import core
from homeassistant.components.media_player import MediaPlayerDevice from homeassistant.components.media_player import MediaPlayerDevice
from homeassistant.components.media_player.const import ( from homeassistant.components.media_player.const import (
@ -18,6 +20,8 @@ from .const import CONF_SOURCES, DOMAIN, SERVICE_RESTORE, SERVICE_SNAPSHOT
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
PARALLEL_UPDATES = 1
SUPPORT_MONOPRICE = ( SUPPORT_MONOPRICE = (
SUPPORT_VOLUME_MUTE SUPPORT_VOLUME_MUTE
| SUPPORT_VOLUME_SET | SUPPORT_VOLUME_SET
@ -127,9 +131,15 @@ class MonopriceZone(MediaPlayerDevice):
def update(self): def update(self):
"""Retrieve latest state.""" """Retrieve latest state."""
state = self._monoprice.zone_status(self._zone_id) try:
state = self._monoprice.zone_status(self._zone_id)
except SerialException:
_LOGGER.warning("Could not update zone %d", self._zone_id)
return
if not state: if not state:
return False return
self._state = STATE_ON if state.power else STATE_OFF self._state = STATE_ON if state.power else STATE_OFF
self._volume = state.volume self._volume = state.volume
self._mute = state.mute self._mute = state.mute
@ -138,7 +148,6 @@ class MonopriceZone(MediaPlayerDevice):
self._source = self._source_id_name[idx] self._source = self._source_id_name[idx]
else: else:
self._source = None self._source = None
return True
@property @property
def entity_registry_enabled_default(self): def entity_registry_enabled_default(self):

View file

@ -294,6 +294,58 @@ async def test_update(hass):
assert state.attributes[ATTR_INPUT_SOURCE] == "three" assert state.attributes[ATTR_INPUT_SOURCE] == "three"
async def test_failed_update(hass):
"""Test updating failure from monoprice."""
monoprice = MockMonoprice()
await _setup_monoprice(hass, monoprice)
# Changing media player to new state
await _call_media_player_service(
hass, SERVICE_VOLUME_SET, {"entity_id": ZONE_1_ID, "volume_level": 0.0}
)
await _call_media_player_service(
hass, SERVICE_SELECT_SOURCE, {"entity_id": ZONE_1_ID, "source": "one"}
)
monoprice.set_source(11, 3)
monoprice.set_volume(11, 38)
with patch.object(MockMonoprice, "zone_status", side_effect=SerialException):
await async_update_entity(hass, ZONE_1_ID)
await hass.async_block_till_done()
state = hass.states.get(ZONE_1_ID)
assert state.attributes[ATTR_MEDIA_VOLUME_LEVEL] == 0.0
assert state.attributes[ATTR_INPUT_SOURCE] == "one"
async def test_empty_update(hass):
"""Test updating with no state from monoprice."""
monoprice = MockMonoprice()
await _setup_monoprice(hass, monoprice)
# Changing media player to new state
await _call_media_player_service(
hass, SERVICE_VOLUME_SET, {"entity_id": ZONE_1_ID, "volume_level": 0.0}
)
await _call_media_player_service(
hass, SERVICE_SELECT_SOURCE, {"entity_id": ZONE_1_ID, "source": "one"}
)
monoprice.set_source(11, 3)
monoprice.set_volume(11, 38)
with patch.object(MockMonoprice, "zone_status", return_value=None):
await async_update_entity(hass, ZONE_1_ID)
await hass.async_block_till_done()
state = hass.states.get(ZONE_1_ID)
assert state.attributes[ATTR_MEDIA_VOLUME_LEVEL] == 0.0
assert state.attributes[ATTR_INPUT_SOURCE] == "one"
async def test_supported_features(hass): async def test_supported_features(hass):
"""Test supported features property.""" """Test supported features property."""
await _setup_monoprice(hass, MockMonoprice()) await _setup_monoprice(hass, MockMonoprice())