Improve error handling, availability logic and state restore
- Add TransferResult enum (SUCCESS, SENT, SERVER_ERROR, NETWORK_ERROR) to distinguish network errors from server errors - Only mark entities as unavailable on NETWORK_ERROR (addon unreachable) - HTTP 401, 405, 500 no longer trigger unavailable state, logged instead - Add RestoreEntity to cover, switch and light to restore last known state after HA restart
This commit is contained in:
@@ -1,13 +1,14 @@
|
||||
"""AirSend lights (dimmable)."""
|
||||
from typing import Any
|
||||
|
||||
from .device import Device
|
||||
from .device import Device, TransferResult
|
||||
|
||||
from homeassistant.components.light import LightEntity, ATTR_BRIGHTNESS, ColorMode
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.entity import DeviceInfo
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
from homeassistant.helpers.restore_state import RestoreEntity
|
||||
from homeassistant.const import CONF_INTERNAL_URL
|
||||
|
||||
from . import DOMAIN
|
||||
@@ -29,7 +30,7 @@ async def async_setup_entry(
|
||||
async_add_entities(entities)
|
||||
|
||||
|
||||
class AirSendLight(LightEntity):
|
||||
class AirSendLight(RestoreEntity, LightEntity):
|
||||
"""Representation of an AirSend dimmable light."""
|
||||
|
||||
_attr_color_mode = ColorMode.BRIGHTNESS
|
||||
@@ -41,7 +42,7 @@ class AirSendLight(LightEntity):
|
||||
self._unique_id = DOMAIN + "_" + str(device.unique_channel_name) + "_light"
|
||||
self._available = True
|
||||
self._is_on = False
|
||||
self._brightness = 255 # HA brightness 0-255
|
||||
self._brightness = 255
|
||||
|
||||
@property
|
||||
def unique_id(self):
|
||||
@@ -73,30 +74,37 @@ class AirSendLight(LightEntity):
|
||||
|
||||
@property
|
||||
def brightness(self) -> int:
|
||||
"""Return brightness in HA scale (0-255)."""
|
||||
return self._brightness
|
||||
|
||||
async def async_added_to_hass(self):
|
||||
"""Restore last known state when added to hass."""
|
||||
await super().async_added_to_hass()
|
||||
last_state = await self.async_get_last_state()
|
||||
if last_state and last_state.state not in ('unavailable', 'unknown'):
|
||||
self._is_on = last_state.state == 'on'
|
||||
if last_state.attributes.get('brightness') is not None:
|
||||
self._brightness = last_state.attributes['brightness']
|
||||
self.async_write_ha_state()
|
||||
|
||||
async def _send(self, note: dict) -> bool:
|
||||
"""Send command and update availability."""
|
||||
result = await self._device.async_transfer(note, self.entity_id)
|
||||
available = result is not False
|
||||
available = result != TransferResult.NETWORK_ERROR
|
||||
if self._available != available:
|
||||
self._available = available
|
||||
self.async_write_ha_state()
|
||||
return available
|
||||
return result in (TransferResult.SUCCESS, TransferResult.SENT)
|
||||
|
||||
async def async_turn_on(self, **kwargs: Any) -> None:
|
||||
"""Turn on or dim the light."""
|
||||
if ATTR_BRIGHTNESS in kwargs:
|
||||
# Convert HA brightness (0-255) to AirSend level (0-100)
|
||||
level = max(1, round(kwargs[ATTR_BRIGHTNESS] / 255 * 100))
|
||||
note = {"method": 1, "type": 9, "value": level}
|
||||
if await self._send(note):
|
||||
self._brightness = kwargs[ATTR_BRIGHTNESS]
|
||||
self._is_on = level > 0
|
||||
self._is_on = True
|
||||
self.async_write_ha_state()
|
||||
else:
|
||||
# Turn on at last brightness
|
||||
level = max(1, round(self._brightness / 255 * 100))
|
||||
note = {"method": 1, "type": 9, "value": level}
|
||||
if await self._send(note):
|
||||
|
||||
Reference in New Issue
Block a user