The Envisalink binary sensor was logging events with a relative timestamp that updated every time it polled, so even when nothing new was happening, the event log would be full of meaningless state changes. Modify the sensor code to use an absolute time which stays stable when there isn't new activity.
103 lines
3.5 KiB
Python
103 lines
3.5 KiB
Python
"""
|
|
Support for Envisalink zone states- represented as binary sensors.
|
|
|
|
For more details about this platform, please refer to the documentation at
|
|
https://home-assistant.io/components/binary_sensor.envisalink/
|
|
"""
|
|
import asyncio
|
|
import logging
|
|
import datetime
|
|
|
|
from homeassistant.core import callback
|
|
from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
|
from homeassistant.components.binary_sensor import BinarySensorDevice
|
|
from homeassistant.components.envisalink import (
|
|
DATA_EVL, ZONE_SCHEMA, CONF_ZONENAME, CONF_ZONETYPE, EnvisalinkDevice,
|
|
SIGNAL_ZONE_UPDATE)
|
|
from homeassistant.const import ATTR_LAST_TRIP_TIME
|
|
from homeassistant.util import dt as dt_util
|
|
|
|
_LOGGER = logging.getLogger(__name__)
|
|
|
|
DEPENDENCIES = ['envisalink']
|
|
|
|
|
|
@asyncio.coroutine
|
|
def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
|
|
"""Set up the Envisalink binary sensor devices."""
|
|
configured_zones = discovery_info['zones']
|
|
|
|
devices = []
|
|
for zone_num in configured_zones:
|
|
device_config_data = ZONE_SCHEMA(configured_zones[zone_num])
|
|
device = EnvisalinkBinarySensor(
|
|
hass,
|
|
zone_num,
|
|
device_config_data[CONF_ZONENAME],
|
|
device_config_data[CONF_ZONETYPE],
|
|
hass.data[DATA_EVL].alarm_state['zone'][zone_num],
|
|
hass.data[DATA_EVL]
|
|
)
|
|
devices.append(device)
|
|
|
|
async_add_devices(devices)
|
|
|
|
|
|
class EnvisalinkBinarySensor(EnvisalinkDevice, BinarySensorDevice):
|
|
"""Representation of an Envisalink binary sensor."""
|
|
|
|
def __init__(self, hass, zone_number, zone_name, zone_type, info,
|
|
controller):
|
|
"""Initialize the binary_sensor."""
|
|
self._zone_type = zone_type
|
|
self._zone_number = zone_number
|
|
|
|
_LOGGER.debug('Setting up zone: %s', zone_name)
|
|
super().__init__(zone_name, info, controller)
|
|
|
|
@asyncio.coroutine
|
|
def async_added_to_hass(self):
|
|
"""Register callbacks."""
|
|
async_dispatcher_connect(
|
|
self.hass, SIGNAL_ZONE_UPDATE, self._update_callback)
|
|
|
|
@property
|
|
def device_state_attributes(self):
|
|
"""Return the state attributes."""
|
|
attr = {}
|
|
|
|
# The Envisalink library returns a "last_fault" value that's the
|
|
# number of seconds since the last fault, up to a maximum of 327680
|
|
# seconds (65536 5-second ticks).
|
|
#
|
|
# We don't want the HA event log to fill up with a bunch of no-op
|
|
# "state changes" that are just that number ticking up once per poll
|
|
# interval, so we subtract it from the current second-accurate time
|
|
# unless it is already at the maximum value, in which case we set it
|
|
# to None since we can't determine the actual value.
|
|
seconds_ago = self._info['last_fault']
|
|
if seconds_ago < 65536 * 5:
|
|
now = dt_util.now().replace(microsecond=0)
|
|
delta = datetime.timedelta(seconds=seconds_ago)
|
|
last_trip_time = (now - delta).isoformat()
|
|
else:
|
|
last_trip_time = None
|
|
|
|
attr[ATTR_LAST_TRIP_TIME] = last_trip_time
|
|
return attr
|
|
|
|
@property
|
|
def is_on(self):
|
|
"""Return true if sensor is on."""
|
|
return self._info['status']['open']
|
|
|
|
@property
|
|
def device_class(self):
|
|
"""Return the class of this sensor, from DEVICE_CLASSES."""
|
|
return self._zone_type
|
|
|
|
@callback
|
|
def _update_callback(self, zone):
|
|
"""Update the zone's state, if needed."""
|
|
if zone is None or int(zone) == self._zone_number:
|
|
self.async_schedule_update_ha_state()
|