Add hysteresis attribute to threshold binary sensor (#9596)

* Added hysteresis attribute to threshold binary sensor

* Added threshold binary sensor hysteresis test case

* Changed threshold binary sensor property name to be more self explanatory

* Pulled default hysteresis value into top level declaration

* Fixed linter errors

* Fixed additional linter errors

* Move comment to docs
This commit is contained in:
Sam Birch 2017-10-03 04:15:19 +13:00 committed by Fabian Affolter
parent b4551cc127
commit da4048a9ec
2 changed files with 73 additions and 11 deletions

View file

@ -20,15 +20,18 @@ from homeassistant.helpers.event import async_track_state_change
_LOGGER = logging.getLogger(__name__)
ATTR_HYSTERESIS = 'hysteresis'
ATTR_SENSOR_VALUE = 'sensor_value'
ATTR_THRESHOLD = 'threshold'
ATTR_TYPE = 'type'
CONF_HYSTERESIS = 'hysteresis'
CONF_LOWER = 'lower'
CONF_THRESHOLD = 'threshold'
CONF_UPPER = 'upper'
DEFAULT_NAME = 'Threshold'
DEFAULT_HYSTERESIS = 0.0
SENSOR_TYPES = [CONF_LOWER, CONF_UPPER]
@ -36,6 +39,8 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
vol.Required(CONF_ENTITY_ID): cv.entity_id,
vol.Required(CONF_THRESHOLD): vol.Coerce(float),
vol.Required(CONF_TYPE): vol.In(SENSOR_TYPES),
vol.Optional(
CONF_HYSTERESIS, default=DEFAULT_HYSTERESIS): vol.Coerce(float),
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
vol.Optional(CONF_DEVICE_CLASS): DEVICE_CLASSES_SCHEMA,
})
@ -47,28 +52,32 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
entity_id = config.get(CONF_ENTITY_ID)
name = config.get(CONF_NAME)
threshold = config.get(CONF_THRESHOLD)
hysteresis = config.get(CONF_HYSTERESIS)
limit_type = config.get(CONF_TYPE)
device_class = config.get(CONF_DEVICE_CLASS)
async_add_devices(
[ThresholdSensor(hass, entity_id, name, threshold, limit_type,
device_class)], True)
async_add_devices([ThresholdSensor(
hass, entity_id, name, threshold,
hysteresis, limit_type, device_class)
], True)
return True
class ThresholdSensor(BinarySensorDevice):
"""Representation of a Threshold sensor."""
def __init__(self, hass, entity_id, name, threshold, limit_type,
device_class):
def __init__(self, hass, entity_id, name, threshold,
hysteresis, limit_type, device_class):
"""Initialize the Threshold sensor."""
self._hass = hass
self._entity_id = entity_id
self.is_upper = limit_type == 'upper'
self._name = name
self._threshold = threshold
self._hysteresis = hysteresis
self._device_class = device_class
self._deviation = False
self._state = False
self.sensor_value = 0
@callback
@ -97,7 +106,7 @@ class ThresholdSensor(BinarySensorDevice):
@property
def is_on(self):
"""Return true if sensor is on."""
return self._deviation
return self._state
@property
def should_poll(self):
@ -116,13 +125,16 @@ class ThresholdSensor(BinarySensorDevice):
ATTR_ENTITY_ID: self._entity_id,
ATTR_SENSOR_VALUE: self.sensor_value,
ATTR_THRESHOLD: self._threshold,
ATTR_HYSTERESIS: self._hysteresis,
ATTR_TYPE: CONF_UPPER if self.is_upper else CONF_LOWER,
}
@asyncio.coroutine
def async_update(self):
"""Get the latest data and updates the states."""
if self.is_upper:
self._deviation = bool(self.sensor_value > self._threshold)
else:
self._deviation = bool(self.sensor_value < self._threshold)
if self._hysteresis == 0 and self.sensor_value == self._threshold:
self._state = False
elif self.sensor_value > (self._threshold + self._hysteresis):
self._state = self.is_upper
elif self.sensor_value < (self._threshold - self._hysteresis):
self._state = not self.is_upper