mirror of
https://github.com/home-assistant/core.git
synced 2025-07-24 13:47:35 +00:00
Add availability to Rflink entities. (#14977)
This commit is contained in:
parent
4bd7a7eee3
commit
2ec295a6f8
@ -20,6 +20,8 @@ from homeassistant.exceptions import HomeAssistantError
|
|||||||
import homeassistant.helpers.config_validation as cv
|
import homeassistant.helpers.config_validation as cv
|
||||||
from homeassistant.helpers.deprecation import get_deprecated
|
from homeassistant.helpers.deprecation import get_deprecated
|
||||||
from homeassistant.helpers.entity import Entity
|
from homeassistant.helpers.entity import Entity
|
||||||
|
from homeassistant.helpers.dispatcher import (
|
||||||
|
async_dispatcher_send, async_dispatcher_connect)
|
||||||
|
|
||||||
|
|
||||||
REQUIREMENTS = ['rflink==0.0.37']
|
REQUIREMENTS = ['rflink==0.0.37']
|
||||||
@ -65,6 +67,8 @@ DOMAIN = 'rflink'
|
|||||||
|
|
||||||
SERVICE_SEND_COMMAND = 'send_command'
|
SERVICE_SEND_COMMAND = 'send_command'
|
||||||
|
|
||||||
|
SIGNAL_AVAILABILITY = 'rflink_device_available'
|
||||||
|
|
||||||
DEVICE_DEFAULTS_SCHEMA = vol.Schema({
|
DEVICE_DEFAULTS_SCHEMA = vol.Schema({
|
||||||
vol.Optional(CONF_FIRE_EVENT, default=False): cv.boolean,
|
vol.Optional(CONF_FIRE_EVENT, default=False): cv.boolean,
|
||||||
vol.Optional(CONF_SIGNAL_REPETITIONS,
|
vol.Optional(CONF_SIGNAL_REPETITIONS,
|
||||||
@ -185,6 +189,8 @@ def async_setup(hass, config):
|
|||||||
# Reset protocol binding before starting reconnect
|
# Reset protocol binding before starting reconnect
|
||||||
RflinkCommand.set_rflink_protocol(None)
|
RflinkCommand.set_rflink_protocol(None)
|
||||||
|
|
||||||
|
async_dispatcher_send(hass, SIGNAL_AVAILABILITY, False)
|
||||||
|
|
||||||
# If HA is not stopping, initiate new connection
|
# If HA is not stopping, initiate new connection
|
||||||
if hass.state != CoreState.stopping:
|
if hass.state != CoreState.stopping:
|
||||||
_LOGGER.warning('disconnected from Rflink, reconnecting')
|
_LOGGER.warning('disconnected from Rflink, reconnecting')
|
||||||
@ -219,9 +225,16 @@ def async_setup(hass, config):
|
|||||||
_LOGGER.exception(
|
_LOGGER.exception(
|
||||||
"Error connecting to Rflink, reconnecting in %s",
|
"Error connecting to Rflink, reconnecting in %s",
|
||||||
reconnect_interval)
|
reconnect_interval)
|
||||||
|
# Connection to Rflink device is lost, make entities unavailable
|
||||||
|
async_dispatcher_send(hass, SIGNAL_AVAILABILITY, False)
|
||||||
|
|
||||||
hass.loop.call_later(reconnect_interval, reconnect, exc)
|
hass.loop.call_later(reconnect_interval, reconnect, exc)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
# There is a valid connection to a Rflink device now so
|
||||||
|
# mark entities as available
|
||||||
|
async_dispatcher_send(hass, SIGNAL_AVAILABILITY, True)
|
||||||
|
|
||||||
# Bind protocol to command class to allow entities to send commands
|
# Bind protocol to command class to allow entities to send commands
|
||||||
RflinkCommand.set_rflink_protocol(
|
RflinkCommand.set_rflink_protocol(
|
||||||
protocol, config[DOMAIN][CONF_WAIT_FOR_ACK])
|
protocol, config[DOMAIN][CONF_WAIT_FOR_ACK])
|
||||||
@ -244,6 +257,7 @@ class RflinkDevice(Entity):
|
|||||||
|
|
||||||
platform = None
|
platform = None
|
||||||
_state = STATE_UNKNOWN
|
_state = STATE_UNKNOWN
|
||||||
|
_available = True
|
||||||
|
|
||||||
def __init__(self, device_id, hass, name=None, aliases=None, group=True,
|
def __init__(self, device_id, hass, name=None, aliases=None, group=True,
|
||||||
group_aliases=None, nogroup_aliases=None, fire_event=False,
|
group_aliases=None, nogroup_aliases=None, fire_event=False,
|
||||||
@ -305,6 +319,23 @@ class RflinkDevice(Entity):
|
|||||||
"""Assume device state until first device event sets state."""
|
"""Assume device state until first device event sets state."""
|
||||||
return self._state is STATE_UNKNOWN
|
return self._state is STATE_UNKNOWN
|
||||||
|
|
||||||
|
@property
|
||||||
|
def available(self):
|
||||||
|
"""Return True if entity is available."""
|
||||||
|
return self._available
|
||||||
|
|
||||||
|
@callback
|
||||||
|
def set_availability(self, availability):
|
||||||
|
"""Update availability state."""
|
||||||
|
self._available = availability
|
||||||
|
self.async_schedule_update_ha_state()
|
||||||
|
|
||||||
|
@asyncio.coroutine
|
||||||
|
def async_added_to_hass(self):
|
||||||
|
"""Register update callback."""
|
||||||
|
async_dispatcher_connect(self.hass, SIGNAL_AVAILABILITY,
|
||||||
|
self.set_availability)
|
||||||
|
|
||||||
|
|
||||||
class RflinkCommand(RflinkDevice):
|
class RflinkCommand(RflinkDevice):
|
||||||
"""Singleton class to make Rflink command interface available to entities.
|
"""Singleton class to make Rflink command interface available to entities.
|
||||||
|
@ -8,6 +8,9 @@ automatic sensor creation.
|
|||||||
import asyncio
|
import asyncio
|
||||||
|
|
||||||
from ..test_rflink import mock_rflink
|
from ..test_rflink import mock_rflink
|
||||||
|
from homeassistant.components.rflink import (
|
||||||
|
CONF_RECONNECT_INTERVAL)
|
||||||
|
from homeassistant.const import STATE_UNKNOWN
|
||||||
|
|
||||||
DOMAIN = 'sensor'
|
DOMAIN = 'sensor'
|
||||||
|
|
||||||
@ -32,7 +35,7 @@ CONFIG = {
|
|||||||
def test_default_setup(hass, monkeypatch):
|
def test_default_setup(hass, monkeypatch):
|
||||||
"""Test all basic functionality of the rflink sensor component."""
|
"""Test all basic functionality of the rflink sensor component."""
|
||||||
# setup mocking rflink module
|
# setup mocking rflink module
|
||||||
event_callback, create, _, _ = yield from mock_rflink(
|
event_callback, create, _, disconnect_callback = yield from mock_rflink(
|
||||||
hass, CONFIG, DOMAIN, monkeypatch)
|
hass, CONFIG, DOMAIN, monkeypatch)
|
||||||
|
|
||||||
# make sure arguments are passed
|
# make sure arguments are passed
|
||||||
@ -100,3 +103,38 @@ def test_disable_automatic_add(hass, monkeypatch):
|
|||||||
|
|
||||||
# make sure new device is not added
|
# make sure new device is not added
|
||||||
assert not hass.states.get('sensor.test2')
|
assert not hass.states.get('sensor.test2')
|
||||||
|
|
||||||
|
|
||||||
|
@asyncio.coroutine
|
||||||
|
def test_entity_availability(hass, monkeypatch):
|
||||||
|
"""If Rflink device is disconnected, entities should become unavailable."""
|
||||||
|
# Make sure Rflink mock does not 'recover' to quickly from the
|
||||||
|
# disconnect or else the unavailability cannot be measured
|
||||||
|
config = CONFIG
|
||||||
|
failures = [True, True]
|
||||||
|
config[CONF_RECONNECT_INTERVAL] = 60
|
||||||
|
|
||||||
|
# Create platform and entities
|
||||||
|
event_callback, create, _, disconnect_callback = yield from mock_rflink(
|
||||||
|
hass, config, DOMAIN, monkeypatch, failures=failures)
|
||||||
|
|
||||||
|
# Entities are available by default
|
||||||
|
assert hass.states.get('sensor.test').state == STATE_UNKNOWN
|
||||||
|
|
||||||
|
# Mock a disconnect of the Rflink device
|
||||||
|
disconnect_callback()
|
||||||
|
|
||||||
|
# Wait for dispatch events to propagate
|
||||||
|
yield from hass.async_block_till_done()
|
||||||
|
|
||||||
|
# Entity should be unavailable
|
||||||
|
assert hass.states.get('sensor.test').state == 'unavailable'
|
||||||
|
|
||||||
|
# Reconnect the Rflink device
|
||||||
|
disconnect_callback()
|
||||||
|
|
||||||
|
# Wait for dispatch events to propagate
|
||||||
|
yield from hass.async_block_till_done()
|
||||||
|
|
||||||
|
# Entities should be available again
|
||||||
|
assert hass.states.get('sensor.test').state == STATE_UNKNOWN
|
||||||
|
Loading…
x
Reference in New Issue
Block a user