Catch Shelly set state exceptions when device is inaccessible (#50064)

This commit is contained in:
Shay Levy 2021-05-04 19:10:28 +03:00 committed by GitHub
parent 786c5db5be
commit c21add195a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 57 additions and 12 deletions

View file

@ -83,24 +83,24 @@ class ShellyCover(ShellyBlockEntity, CoverEntity):
async def async_close_cover(self, **kwargs):
"""Close cover."""
self.control_result = await self.block.set_state(go="close")
self.control_result = await self.set_state(go="close")
self.async_write_ha_state()
async def async_open_cover(self, **kwargs):
"""Open cover."""
self.control_result = await self.block.set_state(go="open")
self.control_result = await self.set_state(go="open")
self.async_write_ha_state()
async def async_set_cover_position(self, **kwargs):
"""Move the cover to a specific position."""
self.control_result = await self.block.set_state(
self.control_result = await self.set_state(
go="to_pos", roller_pos=kwargs[ATTR_POSITION]
)
self.async_write_ha_state()
async def async_stop_cover(self, **_kwargs):
"""Stop the cover."""
self.control_result = await self.block.set_state(go="stop")
self.control_result = await self.set_state(go="stop")
self.async_write_ha_state()
@callback

View file

@ -1,11 +1,13 @@
"""Shelly entity helper."""
from __future__ import annotations
import asyncio
from dataclasses import dataclass
import logging
from typing import Any, Callable
import aioshelly
import async_timeout
from homeassistant.core import callback
from homeassistant.helpers import (
@ -17,7 +19,7 @@ from homeassistant.helpers import (
from homeassistant.helpers.restore_state import RestoreEntity
from . import ShellyDeviceRestWrapper, ShellyDeviceWrapper
from .const import COAP, DATA_CONFIG_ENTRY, DOMAIN, REST
from .const import AIOSHELLY_DEVICE_TIMEOUT_SEC, COAP, DATA_CONFIG_ENTRY, DOMAIN, REST
from .utils import async_remove_shelly_entity, get_entity_name
_LOGGER = logging.getLogger(__name__)
@ -218,6 +220,22 @@ class ShellyBlockEntity(entity.Entity):
"""Handle device update."""
self.async_write_ha_state()
async def set_state(self, **kwargs):
"""Set block state (HTTP request)."""
_LOGGER.debug("Setting state for entity %s, state: %s", self.name, kwargs)
try:
async with async_timeout.timeout(AIOSHELLY_DEVICE_TIMEOUT_SEC):
return await self.block.set_state(**kwargs)
except (asyncio.TimeoutError, OSError) as err:
_LOGGER.error(
"Setting state for entity %s failed, state: %s, error: %s",
self.name,
kwargs,
repr(err),
)
self.wrapper.last_update_success = False
return None
class ShellyBlockAttributeEntity(ShellyBlockEntity, entity.Entity):
"""Helper class to represent a block attribute."""

View file

@ -1,7 +1,11 @@
"""Light for Shelly."""
from __future__ import annotations
import asyncio
import logging
from aioshelly import Block
import async_timeout
from homeassistant.components.light import (
ATTR_BRIGHTNESS,
@ -24,6 +28,7 @@ from homeassistant.util.color import (
from . import ShellyDeviceWrapper
from .const import (
AIOSHELLY_DEVICE_TIMEOUT_SEC,
COAP,
DATA_CONFIG_ENTRY,
DOMAIN,
@ -34,6 +39,8 @@ from .const import (
from .entity import ShellyBlockEntity
from .utils import async_remove_shelly_entity
_LOGGER = logging.getLogger(__name__)
async def async_setup_entry(hass, config_entry, async_add_entities):
"""Set up lights for device."""
@ -199,7 +206,7 @@ class ShellyLight(ShellyBlockEntity, LightEntity):
async def async_turn_on(self, **kwargs) -> None:
"""Turn on light."""
if self.block.type == "relay":
self.control_result = await self.block.set_state(turn="on")
self.control_result = await self.set_state(turn="on")
self.async_write_ha_state()
return
@ -233,17 +240,37 @@ class ShellyLight(ShellyBlockEntity, LightEntity):
ATTR_RGBW_COLOR
]
if set_mode and self.mode != set_mode:
self.mode_result = await self.wrapper.device.switch_light_mode(set_mode)
if await self.set_light_mode(set_mode):
self.control_result = await self.set_state(**params)
self.control_result = await self.block.set_state(**params)
self.async_write_ha_state()
async def async_turn_off(self, **kwargs) -> None:
"""Turn off light."""
self.control_result = await self.block.set_state(turn="off")
self.control_result = await self.set_state(turn="off")
self.async_write_ha_state()
async def set_light_mode(self, set_mode):
"""Change device mode color/white if mode has changed."""
if set_mode is None or self.mode == set_mode:
return True
_LOGGER.debug("Setting light mode for entity %s, mode: %s", self.name, set_mode)
try:
async with async_timeout.timeout(AIOSHELLY_DEVICE_TIMEOUT_SEC):
self.mode_result = await self.wrapper.device.switch_light_mode(set_mode)
except (asyncio.TimeoutError, OSError) as err:
_LOGGER.error(
"Setting light mode for entity %s failed, state: %s, error: %s",
self.name,
set_mode,
repr(err),
)
self.wrapper.last_update_success = False
return False
return True
@callback
def _update_callback(self):
"""When device updates, clear control & mode result that overrides state."""

View file

@ -62,12 +62,12 @@ class RelaySwitch(ShellyBlockEntity, SwitchEntity):
async def async_turn_on(self, **kwargs):
"""Turn on relay."""
self.control_result = await self.block.set_state(turn="on")
self.control_result = await self.set_state(turn="on")
self.async_write_ha_state()
async def async_turn_off(self, **kwargs):
"""Turn off relay."""
self.control_result = await self.block.set_state(turn="off")
self.control_result = await self.set_state(turn="off")
self.async_write_ha_state()
@callback