Fix hdmi_cec entity race (#18753)
* Update shouldn't be called before adding the entity.
* Transitional states from
8adc786bac/include/cectypes.h (L458-L459)
Addressing https://github.com/home-assistant/home-assistant/issues/12846
This commit is contained in:
parent
eec4564c71
commit
debae6ad2e
3 changed files with 57 additions and 53 deletions
|
@ -320,38 +320,39 @@ def setup(hass: HomeAssistant, base_config):
|
||||||
class CecDevice(Entity):
|
class CecDevice(Entity):
|
||||||
"""Representation of a HDMI CEC device entity."""
|
"""Representation of a HDMI CEC device entity."""
|
||||||
|
|
||||||
def __init__(self, hass: HomeAssistant, device, logical) -> None:
|
def __init__(self, device, logical) -> None:
|
||||||
"""Initialize the device."""
|
"""Initialize the device."""
|
||||||
self._device = device
|
self._device = device
|
||||||
self.hass = hass
|
|
||||||
self._icon = None
|
self._icon = None
|
||||||
self._state = STATE_UNKNOWN
|
self._state = STATE_UNKNOWN
|
||||||
self._logical_address = logical
|
self._logical_address = logical
|
||||||
self.entity_id = "%s.%d" % (DOMAIN, self._logical_address)
|
self.entity_id = "%s.%d" % (DOMAIN, self._logical_address)
|
||||||
device.set_update_callback(self._update)
|
|
||||||
|
|
||||||
def update(self):
|
def update(self):
|
||||||
"""Update device status."""
|
"""Update device status."""
|
||||||
self._update()
|
device = self._device
|
||||||
|
from pycec.const import STATUS_PLAY, STATUS_STOP, STATUS_STILL, \
|
||||||
|
POWER_OFF, POWER_ON
|
||||||
|
if device.power_status in [POWER_OFF, 3]:
|
||||||
|
self._state = STATE_OFF
|
||||||
|
elif device.status == STATUS_PLAY:
|
||||||
|
self._state = STATE_PLAYING
|
||||||
|
elif device.status == STATUS_STOP:
|
||||||
|
self._state = STATE_IDLE
|
||||||
|
elif device.status == STATUS_STILL:
|
||||||
|
self._state = STATE_PAUSED
|
||||||
|
elif device.power_status in [POWER_ON, 4]:
|
||||||
|
self._state = STATE_ON
|
||||||
|
else:
|
||||||
|
_LOGGER.warning("Unknown state: %d", device.power_status)
|
||||||
|
|
||||||
|
async def async_added_to_hass(self):
|
||||||
|
"""Register HDMI callbacks after initialization."""
|
||||||
|
self._device.set_update_callback(self._update)
|
||||||
|
|
||||||
def _update(self, device=None):
|
def _update(self, device=None):
|
||||||
"""Update device status."""
|
"""Device status changed, schedule an update."""
|
||||||
if device:
|
self.schedule_update_ha_state(True)
|
||||||
from pycec.const import STATUS_PLAY, STATUS_STOP, STATUS_STILL, \
|
|
||||||
POWER_OFF, POWER_ON
|
|
||||||
if device.power_status == POWER_OFF:
|
|
||||||
self._state = STATE_OFF
|
|
||||||
elif device.status == STATUS_PLAY:
|
|
||||||
self._state = STATE_PLAYING
|
|
||||||
elif device.status == STATUS_STOP:
|
|
||||||
self._state = STATE_IDLE
|
|
||||||
elif device.status == STATUS_STILL:
|
|
||||||
self._state = STATE_PAUSED
|
|
||||||
elif device.power_status == POWER_ON:
|
|
||||||
self._state = STATE_ON
|
|
||||||
else:
|
|
||||||
_LOGGER.warning("Unknown state: %d", device.power_status)
|
|
||||||
self.schedule_update_ha_state()
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def name(self):
|
def name(self):
|
||||||
|
|
|
@ -13,7 +13,6 @@ from homeassistant.components.media_player import (
|
||||||
SUPPORT_VOLUME_MUTE, SUPPORT_VOLUME_STEP, MediaPlayerDevice)
|
SUPPORT_VOLUME_MUTE, SUPPORT_VOLUME_STEP, MediaPlayerDevice)
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
STATE_IDLE, STATE_OFF, STATE_ON, STATE_PAUSED, STATE_PLAYING)
|
STATE_IDLE, STATE_OFF, STATE_ON, STATE_PAUSED, STATE_PLAYING)
|
||||||
from homeassistant.core import HomeAssistant
|
|
||||||
|
|
||||||
DEPENDENCIES = ['hdmi_cec']
|
DEPENDENCIES = ['hdmi_cec']
|
||||||
|
|
||||||
|
@ -26,20 +25,23 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
|
||||||
"""Find and return HDMI devices as +switches."""
|
"""Find and return HDMI devices as +switches."""
|
||||||
if ATTR_NEW in discovery_info:
|
if ATTR_NEW in discovery_info:
|
||||||
_LOGGER.info("Setting up HDMI devices %s", discovery_info[ATTR_NEW])
|
_LOGGER.info("Setting up HDMI devices %s", discovery_info[ATTR_NEW])
|
||||||
add_entities(CecPlayerDevice(hass, hass.data.get(device),
|
entities = []
|
||||||
hass.data.get(device).logical_address) for
|
for device in discovery_info[ATTR_NEW]:
|
||||||
device in discovery_info[ATTR_NEW])
|
hdmi_device = hass.data.get(device)
|
||||||
|
entities.append(CecPlayerDevice(
|
||||||
|
hdmi_device, hdmi_device.logical_address,
|
||||||
|
))
|
||||||
|
add_entities(entities, True)
|
||||||
|
|
||||||
|
|
||||||
class CecPlayerDevice(CecDevice, MediaPlayerDevice):
|
class CecPlayerDevice(CecDevice, MediaPlayerDevice):
|
||||||
"""Representation of a HDMI device as a Media player."""
|
"""Representation of a HDMI device as a Media player."""
|
||||||
|
|
||||||
def __init__(self, hass: HomeAssistant, device, logical) -> None:
|
def __init__(self, device, logical) -> None:
|
||||||
"""Initialize the HDMI device."""
|
"""Initialize the HDMI device."""
|
||||||
CecDevice.__init__(self, hass, device, logical)
|
CecDevice.__init__(self, device, logical)
|
||||||
self.entity_id = "%s.%s_%s" % (
|
self.entity_id = "%s.%s_%s" % (
|
||||||
DOMAIN, 'hdmi', hex(self._logical_address)[2:])
|
DOMAIN, 'hdmi', hex(self._logical_address)[2:])
|
||||||
self.update()
|
|
||||||
|
|
||||||
def send_keypress(self, key):
|
def send_keypress(self, key):
|
||||||
"""Send keypress to CEC adapter."""
|
"""Send keypress to CEC adapter."""
|
||||||
|
@ -137,25 +139,24 @@ class CecPlayerDevice(CecDevice, MediaPlayerDevice):
|
||||||
"""Cache state of device."""
|
"""Cache state of device."""
|
||||||
return self._state
|
return self._state
|
||||||
|
|
||||||
def _update(self, device=None):
|
def update(self):
|
||||||
"""Update device status."""
|
"""Update device status."""
|
||||||
if device:
|
device = self._device
|
||||||
from pycec.const import STATUS_PLAY, STATUS_STOP, STATUS_STILL, \
|
from pycec.const import STATUS_PLAY, STATUS_STOP, STATUS_STILL, \
|
||||||
POWER_OFF, POWER_ON
|
POWER_OFF, POWER_ON
|
||||||
if device.power_status == POWER_OFF:
|
if device.power_status in [POWER_OFF, 3]:
|
||||||
self._state = STATE_OFF
|
self._state = STATE_OFF
|
||||||
elif not self.support_pause:
|
elif not self.support_pause:
|
||||||
if device.power_status == POWER_ON:
|
if device.power_status in [POWER_ON, 4]:
|
||||||
self._state = STATE_ON
|
self._state = STATE_ON
|
||||||
elif device.status == STATUS_PLAY:
|
elif device.status == STATUS_PLAY:
|
||||||
self._state = STATE_PLAYING
|
self._state = STATE_PLAYING
|
||||||
elif device.status == STATUS_STOP:
|
elif device.status == STATUS_STOP:
|
||||||
self._state = STATE_IDLE
|
self._state = STATE_IDLE
|
||||||
elif device.status == STATUS_STILL:
|
elif device.status == STATUS_STILL:
|
||||||
self._state = STATE_PAUSED
|
self._state = STATE_PAUSED
|
||||||
else:
|
else:
|
||||||
_LOGGER.warning("Unknown state: %s", device.status)
|
_LOGGER.warning("Unknown state: %s", device.status)
|
||||||
self.schedule_update_ha_state()
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def supported_features(self):
|
def supported_features(self):
|
||||||
|
|
|
@ -9,7 +9,6 @@ import logging
|
||||||
from homeassistant.components.hdmi_cec import CecDevice, ATTR_NEW
|
from homeassistant.components.hdmi_cec import CecDevice, ATTR_NEW
|
||||||
from homeassistant.components.switch import SwitchDevice, DOMAIN
|
from homeassistant.components.switch import SwitchDevice, DOMAIN
|
||||||
from homeassistant.const import STATE_OFF, STATE_STANDBY, STATE_ON
|
from homeassistant.const import STATE_OFF, STATE_STANDBY, STATE_ON
|
||||||
from homeassistant.core import HomeAssistant
|
|
||||||
|
|
||||||
DEPENDENCIES = ['hdmi_cec']
|
DEPENDENCIES = ['hdmi_cec']
|
||||||
|
|
||||||
|
@ -22,20 +21,23 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
|
||||||
"""Find and return HDMI devices as switches."""
|
"""Find and return HDMI devices as switches."""
|
||||||
if ATTR_NEW in discovery_info:
|
if ATTR_NEW in discovery_info:
|
||||||
_LOGGER.info("Setting up HDMI devices %s", discovery_info[ATTR_NEW])
|
_LOGGER.info("Setting up HDMI devices %s", discovery_info[ATTR_NEW])
|
||||||
add_entities(CecSwitchDevice(hass, hass.data.get(device),
|
entities = []
|
||||||
hass.data.get(device).logical_address) for
|
for device in discovery_info[ATTR_NEW]:
|
||||||
device in discovery_info[ATTR_NEW])
|
hdmi_device = hass.data.get(device)
|
||||||
|
entities.append(CecSwitchDevice(
|
||||||
|
hdmi_device, hdmi_device.logical_address,
|
||||||
|
))
|
||||||
|
add_entities(entities, True)
|
||||||
|
|
||||||
|
|
||||||
class CecSwitchDevice(CecDevice, SwitchDevice):
|
class CecSwitchDevice(CecDevice, SwitchDevice):
|
||||||
"""Representation of a HDMI device as a Switch."""
|
"""Representation of a HDMI device as a Switch."""
|
||||||
|
|
||||||
def __init__(self, hass: HomeAssistant, device, logical) -> None:
|
def __init__(self, device, logical) -> None:
|
||||||
"""Initialize the HDMI device."""
|
"""Initialize the HDMI device."""
|
||||||
CecDevice.__init__(self, hass, device, logical)
|
CecDevice.__init__(self, device, logical)
|
||||||
self.entity_id = "%s.%s_%s" % (
|
self.entity_id = "%s.%s_%s" % (
|
||||||
DOMAIN, 'hdmi', hex(self._logical_address)[2:])
|
DOMAIN, 'hdmi', hex(self._logical_address)[2:])
|
||||||
self.update()
|
|
||||||
|
|
||||||
def turn_on(self, **kwargs) -> None:
|
def turn_on(self, **kwargs) -> None:
|
||||||
"""Turn device on."""
|
"""Turn device on."""
|
||||||
|
|
Loading…
Add table
Reference in a new issue