/**
* 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.em.internal;
import java.util.Dictionary;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.lang.StringUtils;
import org.openhab.binding.em.EMBindingProvider;
import org.openhab.binding.em.internal.EMBindingConfig.Datapoint;
import org.openhab.binding.em.internal.EMBindingConfig.EMType;
import org.openhab.core.binding.AbstractBinding;
import org.openhab.core.library.types.DecimalType;
import org.openhab.io.transport.cul.CULLifecycleListenerListenerRegisterer;
import org.openhab.io.transport.cul.CULLifecycleManager;
import org.openhab.io.transport.cul.CULListener;
import org.openhab.io.transport.cul.CULMode;
import org.osgi.service.cm.ConfigurationException;
import org.osgi.service.cm.ManagedService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Implement this class if you are going create an actively polling service like
* querying a Website/Device.
*
* @author Till Klocke
* @since 1.4.0
*/
public class EMBinding extends AbstractBinding<EMBindingProvider>implements ManagedService, CULListener {
private static final Logger logger = LoggerFactory.getLogger(EMBinding.class);
private final CULLifecycleManager culHandlerLifecycle;
private Map<String, Integer> counterMap = new HashMap<String, Integer>();
public EMBinding() {
culHandlerLifecycle = new CULLifecycleManager(CULMode.SLOW_RF,
new CULLifecycleListenerListenerRegisterer(this));
}
@Override
public void activate() {
culHandlerLifecycle.open();
}
@Override
public void deactivate() {
culHandlerLifecycle.close();
}
protected void addBindingProvider(EMBindingProvider bindingProvider) {
super.addBindingProvider(bindingProvider);
}
protected void removeBindingProvider(EMBindingProvider bindingProvider) {
super.removeBindingProvider(bindingProvider);
}
/**
* @{inheritDoc}
*/
@Override
public void updated(Dictionary<String, ?> config) throws ConfigurationException {
culHandlerLifecycle.config(config);
}
@Override
public void dataReceived(String data) {
if (!StringUtils.isEmpty(data) && data.startsWith("E")) {
parseDataLine(data);
}
}
/**
* Parse the received line of data and create updates for configured items
*
* @param data
*/
private void parseDataLine(String data) {
String address = ParsingUtils.parseAddress(data);
if (!checkNewMessage(address, ParsingUtils.parseCounter(data))) {
logger.warn("Received message from " + address + " more than once");
return;
}
EMType type = ParsingUtils.parseType(data);
EMBindingConfig emConfig = findConfig(type, address, Datapoint.CUMULATED_VALUE);
if (emConfig != null) {
updateItem(emConfig, ParsingUtils.parseCumulatedValue(data));
}
if (data.length() > 10) {
emConfig = findConfig(type, address, Datapoint.LAST_VALUE);
if (emConfig != null) {
updateItem(emConfig, ParsingUtils.parseCurrentValue(data));
}
emConfig = findConfig(type, address, Datapoint.TOP_VALUE);
if (emConfig != null) {
updateItem(emConfig, ParsingUtils.parsePeakValue(data));
}
}
}
/**
* Update an item given in the configuration with the given value multiplied
* by the correction factor
*
* @param config
* @param value
*/
private void updateItem(EMBindingConfig config, int value) {
DecimalType status = new DecimalType(value * config.getCorrectionFactor());
eventPublisher.postUpdate(config.getItem().getName(), status);
}
/**
* Check if we have received a new message to not consume repeated messages
*
* @param address
* @param counter
* @return
*/
private boolean checkNewMessage(String address, int counter) {
Integer lastCounter = counterMap.get(address);
if (lastCounter == null) {
lastCounter = -1;
}
if (counter > lastCounter) {
return true;
}
return false;
}
private EMBindingConfig findConfig(EMType type, String address, Datapoint datapoint) {
EMBindingConfig emConfig = null;
for (EMBindingProvider provider : this.providers) {
emConfig = provider.getConfigByTypeAndAddressAndDatapoint(type, address, datapoint);
if (emConfig != null) {
return emConfig;
}
}
return null;
}
@Override
public void error(Exception e) {
logger.error("Exception instead of new data from CUL", e);
}
}