Skip to content

Commit

Permalink
Fix hdmi_cec entity race
Browse files Browse the repository at this point in the history
Update shouldn't be called before adding the entity.

Addressing #12846
  • Loading branch information
yottatsa committed Nov 28, 2018
1 parent 1f123eb commit 3165364
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 46 deletions.
44 changes: 24 additions & 20 deletions homeassistant/components/hdmi_cec.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
STATE_OFF, CONF_DEVICES, CONF_PLATFORM,
STATE_PLAYING, STATE_IDLE,
STATE_PAUSED, CONF_HOST)
from homeassistant.core import HomeAssistant
from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers.entity import Entity

REQUIREMENTS = ['pyCEC==0.4.13']
Expand Down Expand Up @@ -328,30 +328,34 @@ def __init__(self, hass: HomeAssistant, device, logical) -> None:
self._state = STATE_UNKNOWN
self._logical_address = logical
self.entity_id = "%s.%d" % (DOMAIN, self._logical_address)
device.set_update_callback(self._update)

def update(self):
"""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 == 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)

async def async_added_to_hass(self):
"""Register callbacks after initialization."""
self._device.set_update_callback(self._update)
self.update()

@callback
def _update(self, device=None):
"""Update device status."""
if device:
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()
"""Device status changed, schedule an update."""
self.schedule_update_ha_state(True)

@property
def name(self):
Expand Down
46 changes: 24 additions & 22 deletions homeassistant/components/media_player/hdmi_cec.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,13 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
"""Find and return HDMI devices as +switches."""
if ATTR_NEW in discovery_info:
_LOGGER.info("Setting up HDMI devices %s", discovery_info[ATTR_NEW])
add_entities(CecPlayerDevice(hass, hass.data.get(device),
hass.data.get(device).logical_address) for
device in discovery_info[ATTR_NEW])
entities = []
for device in discovery_info[ATTR_NEW]:
hdmi_device = hass.data.get(device)
entities.append(CecPlayerDevice(
hass, hdmi_device, hdmi_device.logical_address,
))
add_entities(entities, True)


class CecPlayerDevice(CecDevice, MediaPlayerDevice):
Expand All @@ -39,7 +43,6 @@ def __init__(self, hass: HomeAssistant, device, logical) -> None:
CecDevice.__init__(self, hass, device, logical)
self.entity_id = "%s.%s_%s" % (
DOMAIN, 'hdmi', hex(self._logical_address)[2:])
self.update()

def send_keypress(self, key):
"""Send keypress to CEC adapter."""
Expand Down Expand Up @@ -137,25 +140,24 @@ def state(self) -> str:
"""Cache state of device."""
return self._state

def _update(self, device=None):
def update(self):
"""Update device status."""
if device:
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 not self.support_pause:
if device.power_status == POWER_ON:
self._state = STATE_ON
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
else:
_LOGGER.warning("Unknown state: %s", device.status)
self.schedule_update_ha_state()
device = self._device
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 not self.support_pause:
if device.power_status == POWER_ON:
self._state = STATE_ON
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
else:
_LOGGER.warning("Unknown state: %s", device.status)

@property
def supported_features(self):
Expand Down
11 changes: 7 additions & 4 deletions homeassistant/components/switch/hdmi_cec.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,13 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
"""Find and return HDMI devices as switches."""
if ATTR_NEW in discovery_info:
_LOGGER.info("Setting up HDMI devices %s", discovery_info[ATTR_NEW])
add_entities(CecSwitchDevice(hass, hass.data.get(device),
hass.data.get(device).logical_address) for
device in discovery_info[ATTR_NEW])
entities = []
for device in discovery_info[ATTR_NEW]:
hdmi_device = hass.data.get(device)
entities.append(CecSwitchDevice(
hass, hdmi_device, hdmi_device.logical_address,
))
add_entities(entities, True)


class CecSwitchDevice(CecDevice, SwitchDevice):
Expand All @@ -35,7 +39,6 @@ def __init__(self, hass: HomeAssistant, device, logical) -> None:
CecDevice.__init__(self, hass, device, logical)
self.entity_id = "%s.%s_%s" % (
DOMAIN, 'hdmi', hex(self._logical_address)[2:])
self.update()

def turn_on(self, **kwargs) -> None:
"""Turn device on."""
Expand Down

0 comments on commit 3165364

Please sign in to comment.