/**
* 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.harmonyhub.internal;
import java.util.HashMap;
import java.util.Map;
import org.openhab.binding.harmonyhub.HarmonyHubBindingProvider;
import org.openhab.core.binding.AbstractBinding;
import org.openhab.core.binding.BindingProvider;
import org.openhab.core.items.Item;
import org.openhab.core.library.items.NumberItem;
import org.openhab.core.library.types.DecimalType;
import org.openhab.core.library.types.StringType;
import org.openhab.core.types.Command;
import org.openhab.core.types.State;
import org.openhab.io.harmonyhub.HarmonyHubGateway;
import org.openhab.io.harmonyhub.HarmonyHubGatewayListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import net.whistlingfish.harmony.ActivityChangeListener;
import net.whistlingfish.harmony.HarmonyClient;
import net.whistlingfish.harmony.HarmonyHubListener;
import net.whistlingfish.harmony.config.Activity;
/**
* Logitech Harmony Hub Binding for openHAB
*
* The Logitech Harmony Hub is an advanced remote control for various audio, visual
* and home automation devices.
* .
*
* @see <a href="http://www.logitech.com/en-us/harmony-remotes">Logitech Harmony Website</a>
* @author Dan Cunningham
* @since 1.7.0
*/
public class HarmonyHubBinding extends AbstractBinding<HarmonyHubBindingProvider>implements HarmonyHubGatewayListener {
private static final Logger logger = LoggerFactory.getLogger(HarmonyHubBinding.class);
private HarmonyHubGateway harmonyHubGateway;
/**
* Map of qualifiers to listeners
*/
private Map<String, HarmonyHubListener> harmonyListeners;
/**
* @{inheritDoc}
*/
@Override
public void bindingChanged(BindingProvider provider, final String itemName) {
logger.debug("bindingChanged {} {}", provider, itemName);
if (harmonyHubGateway == null) {
return;
}
if (harmonyListeners == null) {
harmonyListeners = new HashMap<String, HarmonyHubListener>();
} else {
for (String qualifier : harmonyListeners.keySet()) {
harmonyHubGateway.removeListener(qualifier, harmonyListeners.get(qualifier));
}
harmonyListeners.clear();
}
if (provider instanceof HarmonyHubBindingProvider) {
HarmonyHubBindingProvider harmonyProvider = (HarmonyHubBindingProvider) provider;
final HarmonyHubBindingConfig config = harmonyProvider.getHarmonyHubBindingConfig(itemName);
if (harmonyHubGateway != null && config != null
&& config.getBindingType() == HarmonyHubBindingType.CurrentActivity) {
if (!harmonyListeners.containsKey(config.getQualifier())) {
logger.debug("adding new listener for {}", config.getQualifier());
HarmonyHubListener listener = new HarmonyHubListener() {
@Override
public void removeFrom(HarmonyClient client) {
logger.debug("removeFrom called for {}", config.getQualifier());
}
@Override
public void addTo(HarmonyClient client) {
client.addListener(new ActivityChangeListener() {
@Override
public void activityStarted(Activity activity) {
logger.debug("activityStarted called for {}", config.getQualifier());
updateActivity(activity, config.getQualifier());
}
});
// now that we can hear about activity changes, make sure we get the current value
updateActivity(client.getCurrentActivity(), config.getQualifier());
}
};
harmonyHubGateway.addListener(config.getQualifier(), listener);
harmonyListeners.put(config.getQualifier(), listener);
}
}
}
}
/**
* {@inheritDoc}
*/
@Override
public void allBindingsChanged(BindingProvider provider) {
for (String itemName : provider.getItemNames()) {
bindingChanged(provider, itemName);
}
}
protected void addBindingProvider(HarmonyHubBindingProvider bindingProvider) {
super.addBindingProvider(bindingProvider);
}
protected void removeBindingProvider(HarmonyHubBindingProvider bindingProvider) {
super.removeBindingProvider(bindingProvider);
}
/**
* {@inheritDoc}
*/
@Override
protected void internalReceiveCommand(String itemName, Command command) {
logger.debug("internalReceiveCommand({},{}) is called!", itemName, command);
if (harmonyHubGateway == null) {
logger.warn("A command was received, but could not be executed as no Harmony Hub has been configured");
return;
}
for (HarmonyHubBindingProvider provider : providers) {
HarmonyHubBindingConfig config = provider.getHarmonyHubBindingConfig(itemName);
if (config.getBindingType().getDirection() == HarmonyHubBindingDirection.IN) {
logger.warn(
"item {} is not configured to send outbound commands! Please change to > or * in the binding");
continue;
}
switch (config.getBindingType()) {
case PressButton:
logger.debug("PressButton command:{} q:{} p1:{} p2:{}", command.toString(), config.getQualifier(),
config.getParam1(), config.getParam2());
String cmd = config.getParam2();
if (cmd == null) {
cmd = command.toString();
}
try {
harmonyHubGateway.pressButton(config.getQualifier(), Integer.parseInt(config.getParam1()), cmd);
} catch (NumberFormatException ignored) {
harmonyHubGateway.pressButton(config.getQualifier(), config.getParam1(), cmd);
}
break;
case StartActivity:
try {
harmonyHubGateway.startActivity(config.getQualifier(), Integer.parseInt(config.getParam1()));
} catch (NumberFormatException ignored) {
harmonyHubGateway.startActivity(config.getQualifier(), config.getParam1());
}
break;
case CurrentActivity:
harmonyHubGateway.startActivity(config.getQualifier(), command.toString());
break;
default:
break;
}
}
}
/**
* For a given {@link Activity}, update all items who need to know about it
*
* @param activity
*/
private void updateActivity(Activity activity, String qualifier) {
logger.debug("updateActivity {}" + activity.getLabel());
for (HarmonyHubBindingProvider provider : providers) {
for (String itemName : provider.getItemNames()) {
HarmonyHubBindingConfig config = provider.getHarmonyHubBindingConfig(itemName);
if (config.matchesQualifier(qualifier)
&& config.getBindingType() == HarmonyHubBindingType.CurrentActivity) {
updateActivityForItem(itemName, config.getItemType(), activity);
}
}
}
}
/**
* For a given {@link Activity}, update an {@link Item} with its {@link State} state
*
* @param item
* @param state
* @param activity
*/
private void updateActivityForItem(String itemName, Class<? extends Item> itemType, Activity activity) {
if (itemType.isAssignableFrom(NumberItem.class)) {
eventPublisher.postUpdate(itemName, new DecimalType(activity.getId()));
} else {
eventPublisher.postUpdate(itemName, new StringType(activity.getLabel()));
}
}
/**
* Wire up our gateway from the IO bundle
*
* @param harmonyHubGateway
*/
public void setHarmonyHubGateway(HarmonyHubGateway harmonyHubGateway) {
logger.debug("addHarmonyHubGateway, configured {}", harmonyHubGateway.isProperlyConfigured());
this.harmonyHubGateway = harmonyHubGateway;
this.harmonyHubGateway.addHarmonyHubGatewayListener(this);
}
/**
* un-wire our gateway from the IO package
*
* @param harmonyHubGateway
*/
public void unsetHarmonyHubGateway(HarmonyHubGateway harmonyHubGateway) {
this.harmonyHubGateway = null;
}
/**
* Callback from the IO bundle that it is configured
*/
@Override
public void configured(boolean isConfigured) {
if (isConfigured) {
for (HarmonyHubBindingProvider provider : providers) {
allBindingsChanged(provider);
}
}
}
}