/** * Copyright (c) 2010-2016 by the respective copyright holders. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html */ package org.openhab.binding.homematic.internal.communicator; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Timer; import java.util.TimerTask; import org.openhab.binding.homematic.internal.common.HomematicContext; import org.openhab.binding.homematic.internal.communicator.ProviderItemIterator.ProviderItemIteratorCallback; import org.openhab.binding.homematic.internal.config.binding.ActionConfig; import org.openhab.binding.homematic.internal.config.binding.HomematicBindingConfig; import org.openhab.binding.homematic.internal.config.binding.ProgramConfig; import org.openhab.binding.homematic.internal.converter.state.Converter; import org.openhab.binding.homematic.internal.model.HmValueItem; import org.openhab.core.items.Item; import org.openhab.core.library.types.OnOffType; import org.openhab.core.types.State; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Class that sends OFF to items bound to a Homematic PRESS_* datapoint. This is * necessary because Homematic only sends ON for PRESS_* datapoints, so we have * to send OFF after a short delay. It's not possible to send the OFF command * immediately after the ON command, because i saw that sometimes the OFF * command receives before the ON command on the openHAB bus. * * @author Gerhard Riegler * @since 1.5.0 */ public class ItemDisabler extends TimerTask { private static final Logger logger = LoggerFactory.getLogger(ItemDisabler.class); private static final long TIMER_DELAY = 1000; private static final long MIN_AGE = 2000; private HomematicContext context = HomematicContext.getInstance(); private Map<HomematicBindingConfig, Long> itemsToDisable = new HashMap<HomematicBindingConfig, Long>(); private Timer timer; /** * Starts the ItemDisabler timer. */ public void start() { logger.debug("Starting {}", ItemDisabler.class.getSimpleName()); timer = new Timer(); timer.scheduleAtFixedRate(this, TIMER_DELAY, TIMER_DELAY); } /** * Stops the ItemDisabler timer. */ public void stop() { logger.debug("Stopping {}", ItemDisabler.class.getSimpleName()); this.cancel(); timer.cancel(); } /** * Adds a binding to send a OFF command after a short delay. */ public void add(HomematicBindingConfig bindingConfig) { itemsToDisable.put(bindingConfig, System.currentTimeMillis()); } /** * Sends the OFF commands to the openHAB bus. */ @Override public void run() { Iterator<Map.Entry<HomematicBindingConfig, Long>> iterator = itemsToDisable.entrySet().iterator(); while (iterator.hasNext()) { Map.Entry<HomematicBindingConfig, Long> entry = iterator.next(); long diff = System.currentTimeMillis() - entry.getValue(); if (diff > MIN_AGE) { new ProviderItemIterator().iterate(entry.getKey(), new ProviderItemIteratorCallback() { @Override public void next(HomematicBindingConfig providerBindingConfig, Item item, Converter<?> converter) { HmValueItem hmValueItem = context.getStateHolder().getState(providerBindingConfig); if (providerBindingConfig instanceof ProgramConfig || providerBindingConfig instanceof ActionConfig) { context.getEventPublisher().postUpdate(item.getName(), OnOffType.OFF); } else { hmValueItem.setValue(converter.convertToBinding(OnOffType.OFF, hmValueItem)); State state = converter.convertFromBinding(hmValueItem); context.getEventPublisher().postUpdate(item.getName(), state); } logger.debug("Disabled Item {} with binding {}", item.getName(), providerBindingConfig); } }); iterator.remove(); } } } }