Prevent toogle to false at restart of ADS platforms (#22522)

* Prevent toogle to false at restart

* change to asyncio.run_coroutine_threadsafe
This commit is contained in:
carstenschroeder 2019-03-30 18:47:39 +01:00 committed by Martin Hjelmare
parent 2e375aa802
commit 34324afbde
3 changed files with 72 additions and 9 deletions

View file

@ -1,5 +1,7 @@
"""Support for ADS binary sensors.""" """Support for ADS binary sensors."""
import logging import logging
import asyncio
import async_timeout
import voluptuous as vol import voluptuous as vol
@ -41,10 +43,11 @@ class AdsBinarySensor(BinarySensorDevice):
"""Initialize ADS binary sensor.""" """Initialize ADS binary sensor."""
self._name = name self._name = name
self._unique_id = ads_var self._unique_id = ads_var
self._state = False self._state = None
self._device_class = device_class or 'moving' self._device_class = device_class or 'moving'
self._ads_hub = ads_hub self._ads_hub = ads_hub
self.ads_var = ads_var self.ads_var = ads_var
self._event = None
async def async_added_to_hass(self): async def async_added_to_hass(self):
"""Register device notification.""" """Register device notification."""
@ -52,11 +55,24 @@ class AdsBinarySensor(BinarySensorDevice):
"""Handle device notifications.""" """Handle device notifications."""
_LOGGER.debug('Variable %s changed its value to %d', name, value) _LOGGER.debug('Variable %s changed its value to %d', name, value)
self._state = value self._state = value
asyncio.run_coroutine_threadsafe(async_event_set(), self.hass.loop)
self.schedule_update_ha_state() self.schedule_update_ha_state()
self.hass.async_add_job( async def async_event_set():
"""Set event in async context."""
self._event.set()
self._event = asyncio.Event()
await self.hass.async_add_executor_job(
self._ads_hub.add_device_notification, self._ads_hub.add_device_notification,
self.ads_var, self._ads_hub.PLCTYPE_BOOL, update) self.ads_var, self._ads_hub.PLCTYPE_BOOL, update)
try:
with async_timeout.timeout(10):
await self._event.wait()
except asyncio.TimeoutError:
_LOGGER.debug('Variable %s: Timeout during first update',
self.ads_var)
@property @property
def name(self): def name(self):
@ -82,3 +98,8 @@ class AdsBinarySensor(BinarySensorDevice):
def should_poll(self): def should_poll(self):
"""Return False because entity pushes its state to HA.""" """Return False because entity pushes its state to HA."""
return False return False
@property
def available(self):
"""Return False if state has not been updated yet."""
return self._state is not None

View file

@ -1,5 +1,7 @@
"""Support for ADS light sources.""" """Support for ADS light sources."""
import logging import logging
import asyncio
import async_timeout
import voluptuous as vol import voluptuous as vol
@ -30,7 +32,7 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
name = config.get(CONF_NAME) name = config.get(CONF_NAME)
add_entities([AdsLight(ads_hub, ads_var_enable, ads_var_brightness, add_entities([AdsLight(ads_hub, ads_var_enable, ads_var_brightness,
name)], True) name)])
class AdsLight(Light): class AdsLight(Light):
@ -39,12 +41,13 @@ class AdsLight(Light):
def __init__(self, ads_hub, ads_var_enable, ads_var_brightness, name): def __init__(self, ads_hub, ads_var_enable, ads_var_brightness, name):
"""Initialize AdsLight entity.""" """Initialize AdsLight entity."""
self._ads_hub = ads_hub self._ads_hub = ads_hub
self._on_state = False self._on_state = None
self._brightness = None self._brightness = None
self._name = name self._name = name
self._unique_id = ads_var_enable self._unique_id = ads_var_enable
self.ads_var_enable = ads_var_enable self.ads_var_enable = ads_var_enable
self.ads_var_brightness = ads_var_brightness self.ads_var_brightness = ads_var_brightness
self._event = None
async def async_added_to_hass(self): async def async_added_to_hass(self):
"""Register device notification.""" """Register device notification."""
@ -52,24 +55,37 @@ class AdsLight(Light):
"""Handle device notifications for state.""" """Handle device notifications for state."""
_LOGGER.debug('Variable %s changed its value to %d', name, value) _LOGGER.debug('Variable %s changed its value to %d', name, value)
self._on_state = value self._on_state = value
asyncio.run_coroutine_threadsafe(async_event_set(), self.hass.loop)
self.schedule_update_ha_state() self.schedule_update_ha_state()
async def async_event_set():
"""Set event in async context."""
self._event.set()
def update_brightness(name, value): def update_brightness(name, value):
"""Handle device notification for brightness.""" """Handle device notification for brightness."""
_LOGGER.debug('Variable %s changed its value to %d', name, value) _LOGGER.debug('Variable %s changed its value to %d', name, value)
self._brightness = value self._brightness = value
self.schedule_update_ha_state() self.schedule_update_ha_state()
self.hass.async_add_executor_job( self._event = asyncio.Event()
await self.hass.async_add_executor_job(
self._ads_hub.add_device_notification, self._ads_hub.add_device_notification,
self.ads_var_enable, self._ads_hub.PLCTYPE_BOOL, update_on_state self.ads_var_enable, self._ads_hub.PLCTYPE_BOOL, update_on_state
) )
if self.ads_var_brightness is not None: if self.ads_var_brightness is not None:
self.hass.async_add_executor_job( await self.hass.async_add_executor_job(
self._ads_hub.add_device_notification, self._ads_hub.add_device_notification,
self.ads_var_brightness, self._ads_hub.PLCTYPE_INT, self.ads_var_brightness, self._ads_hub.PLCTYPE_INT,
update_brightness update_brightness
) )
try:
with async_timeout.timeout(10):
await self._event.wait()
except asyncio.TimeoutError:
_LOGGER.debug('Variable %s: Timeout during first update',
self.ads_var_enable)
@property @property
def name(self): def name(self):
@ -104,6 +120,11 @@ class AdsLight(Light):
support = SUPPORT_BRIGHTNESS support = SUPPORT_BRIGHTNESS
return support return support
@property
def available(self):
"""Return False if state has not been updated yet."""
return self._on_state is not None
def turn_on(self, **kwargs): def turn_on(self, **kwargs):
"""Turn the light on or set a specific dimmer value.""" """Turn the light on or set a specific dimmer value."""
brightness = kwargs.get(ATTR_BRIGHTNESS) brightness = kwargs.get(ATTR_BRIGHTNESS)

View file

@ -1,5 +1,7 @@
"""Support for ADS switch platform.""" """Support for ADS switch platform."""
import logging import logging
import asyncio
import async_timeout
import voluptuous as vol import voluptuous as vol
@ -29,7 +31,7 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
name = config.get(CONF_NAME) name = config.get(CONF_NAME)
ads_var = config.get(CONF_ADS_VAR) ads_var = config.get(CONF_ADS_VAR)
add_entities([AdsSwitch(ads_hub, name, ads_var)], True) add_entities([AdsSwitch(ads_hub, name, ads_var)])
class AdsSwitch(ToggleEntity): class AdsSwitch(ToggleEntity):
@ -38,10 +40,11 @@ class AdsSwitch(ToggleEntity):
def __init__(self, ads_hub, name, ads_var): def __init__(self, ads_hub, name, ads_var):
"""Initialize the AdsSwitch entity.""" """Initialize the AdsSwitch entity."""
self._ads_hub = ads_hub self._ads_hub = ads_hub
self._on_state = False self._on_state = None
self._name = name self._name = name
self._unique_id = ads_var self._unique_id = ads_var
self.ads_var = ads_var self.ads_var = ads_var
self._event = None
async def async_added_to_hass(self): async def async_added_to_hass(self):
"""Register device notification.""" """Register device notification."""
@ -49,11 +52,24 @@ class AdsSwitch(ToggleEntity):
"""Handle device notification.""" """Handle device notification."""
_LOGGER.debug("Variable %s changed its value to %d", name, value) _LOGGER.debug("Variable %s changed its value to %d", name, value)
self._on_state = value self._on_state = value
asyncio.run_coroutine_threadsafe(async_event_set(), self.hass.loop)
self.schedule_update_ha_state() self.schedule_update_ha_state()
self.hass.async_add_job( async def async_event_set():
"""Set event in async context."""
self._event.set()
self._event = asyncio.Event()
await self.hass.async_add_executor_job(
self._ads_hub.add_device_notification, self._ads_hub.add_device_notification,
self.ads_var, self._ads_hub.PLCTYPE_BOOL, update) self.ads_var, self._ads_hub.PLCTYPE_BOOL, update)
try:
with async_timeout.timeout(10):
await self._event.wait()
except asyncio.TimeoutError:
_LOGGER.debug('Variable %s: Timeout during first update',
self.ads_var)
@property @property
def is_on(self): def is_on(self):
@ -75,6 +91,11 @@ class AdsSwitch(ToggleEntity):
"""Return False because entity pushes its state to HA.""" """Return False because entity pushes its state to HA."""
return False return False
@property
def available(self):
"""Return False if state has not been updated yet."""
return self._on_state is not None
def turn_on(self, **kwargs): def turn_on(self, **kwargs):
"""Turn the switch on.""" """Turn the switch on."""
self._ads_hub.write_by_name( self._ads_hub.write_by_name(