import logging import voluptuous as vol import homeassistant.helpers.config_validation as cv from homeassistant.helpers.event import async_track_state_change, async_call_later from collections import namedtuple, defaultdict import time from functools import partial _LOGGER = logging.getLogger(__name__) CONF_DURATION = "duration" CONF_SWITCHES = "switches" DOMAIN = 'long_click' CONFIG_SCHEMA = vol.Schema({ DOMAIN: vol.Schema({ vol.Optional(CONF_DURATION, default=1.0): float, vol.Required(CONF_SWITCHES): cv.entity_ids} ) }, extra=vol.ALLOW_EXTRA) ButtonInfo = namedtuple('ButtonInfo', ['cancel', 'last_on_time']) switch_on_times = defaultdict(ButtonInfo) def on_rising_edge(entity_id, from_state, to_state, hass, long_click_time): async def long_press_cb(t): hass.bus.fire('long_click', {'entity_id': entity_id}) duration = time.time() - switch_on_times[entity_id].last_on_time assert duration >= long_click_time del switch_on_times[entity_id] cancel_func = async_call_later(hass, long_click_time, long_press_cb) switch_on_times[entity_id] = ButtonInfo(cancel_func, time.time()) def on_falling_edge(entity_id, from_state, to_state, hass, long_click_time): if entity_id in switch_on_times: # cancel callback switch_on_times[entity_id].cancel() duration = time.time() - switch_on_times[entity_id].last_on_time # in case the callback didn't fire yet, even if longer than one second if duration < long_click_time: hass.bus.fire('short_click', {'entity_id': entity_id}) else: hass.bus.fire('long_click', {'entity_id': entity_id}) del switch_on_times[entity_id] async def async_setup(hass, config): duration = config[DOMAIN][CONF_DURATION] async_track_state_change(hass, config[DOMAIN][CONF_SWITCHES], partial(on_rising_edge, hass=hass, long_click_time=duration), 'off', 'on') async_track_state_change(hass, config[DOMAIN][CONF_SWITCHES], partial(on_falling_edge, hass=hass, long_click_time=duration), 'on', 'off') return True