diff --git a/config_creation/manual_config.yaml b/config_creation/manual_config.yaml index de6d561..b9a5c8b 100644 --- a/config_creation/manual_config.yaml +++ b/config_creation/manual_config.yaml @@ -99,6 +99,19 @@ notify: dimmer: cover_half: +long_click: + duration: 1.0 + switches: + - switch.esszimmer_szene_0 + - switch.esszimmer_szene_1 + - switch.esszimmer_szene_2 + - switch.esszimmer_szene_3 + - switch.esszimmer_szene_4 + - switch.esszimmer_szene_5 + - switch.eingang_szene_2 + - switch.eingang_szene_3 + - switch.eingang_szene_4 + - switch.eingang_szene_5 logger: default: info diff --git a/custom_components/long_click/__init__.py b/custom_components/long_click/__init__.py new file mode 100644 index 0000000..8ac174e --- /dev/null +++ b/custom_components/long_click/__init__.py @@ -0,0 +1,58 @@ +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}) + print("-------------------- long on falling edge", entity_id, duration) + 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