/**
* 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.networkupstools.internal;
import java.util.Dictionary;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.lang.StringUtils;
import org.networkupstools.jnut.Client;
import org.networkupstools.jnut.Device;
import org.networkupstools.jnut.Variable;
import org.openhab.binding.networkupstools.NetworkUpsToolsBindingProvider;
import org.openhab.core.binding.AbstractActiveBinding;
import org.openhab.core.items.Item;
import org.openhab.core.library.items.NumberItem;
import org.openhab.core.library.items.StringItem;
import org.openhab.core.library.items.SwitchItem;
import org.openhab.core.library.types.DecimalType;
import org.openhab.core.library.types.OnOffType;
import org.openhab.core.library.types.StringType;
import org.openhab.core.types.State;
import org.osgi.service.cm.ConfigurationException;
import org.osgi.service.cm.ManagedService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
/**
* The RefreshService polls all configured ups parameters with a configurable
* interval and post all values to the internal event bus. The interval is 1
* minute by default and can be changed via openhab.cfg.
*
* @author jaroslawmazgaj
* @since 1.7.0
*/
public class NetworkUpsToolsBinding extends AbstractActiveBinding<NetworkUpsToolsBindingProvider>
implements ManagedService {
private static final Logger logger = LoggerFactory.getLogger(NetworkUpsToolsBinding.class);
private Map<String, NutConfig> upses = new HashMap<String, NutConfig>();
/**
* the refresh interval which is used to poll values from the NetworkUpsTools
* server (optional, defaults to 60000ms)
*/
private long refreshInterval = 60000;
/**
* @{inheritDoc}
*/
@Override
protected long getRefreshInterval() {
return refreshInterval;
}
/**
* @{inheritDoc}
*/
@Override
protected String getName() {
return "NetworkUpsTools Refresh Service";
}
/**
* @{inheritDoc}
*/
@Override
protected void execute() {
Multimap<String, ItemDefinition> items = HashMultimap.create();
for (NetworkUpsToolsBindingProvider provider : providers) {
for (String itemName : provider.getItemNames()) {
String name = provider.getUps(itemName);
Class<? extends Item> itemType = provider.getItemType(itemName);
String property = provider.getProperty(itemName);
items.put(name, new ItemDefinition(itemName, itemType, property));
}
}
for (String name : items.keySet()) {
NutConfig nut = upses.get(name);
if (nut == null) {
logger.error("No configuration for UPS with name: '{}'", name);
continue;
}
Client client = null;
try {
client = new Client(nut.host, nut.port, nut.login, nut.pass);
Device device = client.getDevice(nut.device);
for (ItemDefinition definition : items.get(name)) {
Variable variable = device.getVariable(definition.property);
String value = variable.getValue();
Class<? extends Item> itemType = definition.itemType;
String itemName = definition.itemName;
// Change to a state
State state = null;
if (itemType.isAssignableFrom(StringItem.class)) {
state = StringType.valueOf(value);
} else if (itemType.isAssignableFrom(NumberItem.class)) {
state = DecimalType.valueOf(value);
} else if (itemType.isAssignableFrom(SwitchItem.class)) {
state = OnOffType.valueOf(value);
}
if (state != null) {
eventPublisher.postUpdate(itemName, state);
} else {
logger.error(
"'{}' couldn't be parsed to a State. Valid State-Types are String, Number and Switch",
variable.toString());
}
}
} catch (Exception ex) {
logger.error("Nut processing error", ex);
} finally {
if (client != null) {
client.disconnect();
}
}
}
}
protected void addBindingProvider(NetworkUpsToolsBindingProvider bindingProvider) {
super.addBindingProvider(bindingProvider);
}
protected void removeBindingProvider(NetworkUpsToolsBindingProvider bindingProvider) {
super.removeBindingProvider(bindingProvider);
}
/**
* @{inheritDoc}
*/
@Override
public void updated(Dictionary<String, ?> config) throws ConfigurationException {
if (config != null) {
String refreshIntervalString = (String) config.get("refresh");
if (StringUtils.isNotBlank(refreshIntervalString)) {
refreshInterval = Long.parseLong(refreshIntervalString);
}
Map<String, NutConfig> newUpses = new HashMap<String, NutConfig>();
Enumeration<String> keys = config.keys();
while (keys.hasMoreElements()) {
String key = keys.nextElement();
if ("refresh".equals(key) || "service.pid".equals(key)) {
continue;
}
String[] parts = key.split("\\.");
String name = parts[0];
String prop = parts[1];
String value = (String) config.get(key);
NutConfig nutConfig = newUpses.get(name);
if (nutConfig == null) {
nutConfig = new NutConfig();
newUpses.put(name, nutConfig);
}
if ("device".equalsIgnoreCase(prop)) {
nutConfig.device = value;
} else if ("host".equalsIgnoreCase(prop)) {
nutConfig.host = value;
} else if ("login".equalsIgnoreCase(prop)) {
nutConfig.login = value;
} else if ("pass".equalsIgnoreCase(prop)) {
nutConfig.pass = value;
} else if ("port".equalsIgnoreCase(prop)) {
nutConfig.port = Integer.parseInt(value);
}
}
upses = newUpses;
setProperlyConfigured(true);
}
}
/**
* This is an internal data structure to store nut server configuration
*/
class NutConfig {
String device;
String host = "localhost";
String login = "";
String pass = "";
int port = 3493;
}
/**
* This is an internal data structure to store item definition details for given nut server
*/
class ItemDefinition {
String itemName;
Class<? extends Item> itemType;
String property;
public ItemDefinition(String itemName, Class<? extends Item> itemType, String property) {
this.itemName = itemName;
this.itemType = itemType;
this.property = property;
}
}
}