/**
* Copyright (c) 2010-2016, openHAB.org and others.
*
* 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.fatekplc.items;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.commons.lang.StringUtils;
import org.openhab.core.binding.BindingConfig;
import org.openhab.core.items.Item;
import org.openhab.core.library.items.ColorItem;
import org.openhab.core.library.items.ContactItem;
import org.openhab.core.library.items.DateTimeItem;
import org.openhab.core.library.items.DimmerItem;
import org.openhab.core.library.items.NumberItem;
import org.openhab.core.library.items.RollershutterItem;
import org.openhab.core.library.items.SwitchItem;
import org.openhab.core.types.Command;
import org.openhab.core.types.State;
import org.openhab.model.item.binding.BindingConfigParseException;
import org.simplify4u.jfatek.FatekPLC;
import org.simplify4u.jfatek.registers.Reg;
import org.simplify4u.jfatek.registers.RegValue;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Default Fatek item implementation.
*
* @author Slawomir Jaranowski
* @since 1.9.0
*/
public abstract class FatekPLCItem implements BindingConfig {
/**
* Supported Items Types by Fatek PLC
*
* @author Slawomir Jaranowski
*/
enum ItemsTypes {
COLOR(ColorItem.class),
CONTACT(ContactItem.class),
DATETIME(DateTimeItem.class),
DIMMER(DimmerItem.class),
NUMBER(NumberItem.class),
ROLLERSHUTTER(RollershutterItem.class),
SWITCH(SwitchItem.class);
private Class<? extends Item> aClass;
private ItemsTypes(Class<? extends Item> aclass) {
this.aClass = aclass;
}
public static ItemsTypes find(Class<? extends Item> aClass) {
for (ItemsTypes v : values()) {
if (v.aClass.equals(aClass)) {
return v;
}
}
return null;
}
}
private static final Logger logger = LoggerFactory.getLogger(FatekPLCItem.class);
private static final Pattern PARAM_CONFIG_PATTERN = Pattern.compile("(\\w+)='?(.+)'?");
// fields
private String slaveName;
private String itemName;
protected Reg reg1;
/**
* How often refresh should occur.
*/
private int refreshStep;
private int currentRefreshStep;
/**
* Validates if the <code>item</code> is valid for this binding.
*
* @param item item to check
* @throws BindingConfigParseException
*/
public static void validateItemType(Item item) throws BindingConfigParseException {
logger.debug("validateItemType: {}", item);
if (ItemsTypes.find(item.getClass()) == null) {
throw new BindingConfigParseException(String.format("Item %s class %s not supported by Fatek PLC",
item.getName(), item.getClass().getName()));
}
}
/**
* Create the corresponding Fatek item for given type.
* @param item OpenHab item
* @param bindingConfig config
* @return corresponding Fatek Item for given item type
* @throws BindingConfigParseException
*/
public static FatekPLCItem parseBindingConfiguration(Item item, String bindingConfig)
throws BindingConfigParseException {
if (StringUtils.isBlank(bindingConfig)) {
throw new BindingConfigParseException("bindconfig is empty");
}
List<String> confItems = new ArrayList<>(Arrays.asList(StringUtils.split(bindingConfig, ':')));
if (confItems.size() < 2) {
throw new BindingConfigParseException(String.format("Incorrect binding config: %s", bindingConfig));
}
FatekPLCItem config;
switch (ItemsTypes.find(item.getClass())) {
case COLOR:
config = new FatekColorItem(item, confItems);
break;
case CONTACT:
config = new FatekContactItem(item, confItems);
break;
case DATETIME:
config = new FatekDateTimeItem(item, confItems);
break;
case DIMMER:
config = new FatekDimmerItem(item, confItems);
break;
case NUMBER:
config = new FatekNumberItem(item, confItems);
break;
case ROLLERSHUTTER:
config = new FatekRollershutterItem(item, confItems);
break;
case SWITCH:
config = new FatekSwitchItem(item, confItems);
break;
default:
throw new BindingConfigParseException(String.format("Item %s class %s not supported by Fatek PLC",
item.getName(), item.getClass().getName()));
}
return config;
}
public FatekPLCItem(Item item, List<String> confItems) throws BindingConfigParseException {
itemName = item.getName();
slaveName = confItems.remove(0);
refreshStep = getParamsFromConfAsInt(confItems, "refreshStep", 1);
currentRefreshStep = 1;
}
public String getSlaveName() {
return slaveName;
}
public String getItemName() {
return itemName;
}
/**
* Test if in current update cycle item should be refreshed.
*
* @return true if item should be refreshed.
*/
public boolean isToRefresh() {
// update item on every refresh cycle
if (refreshStep == 1) {
return true;
}
if (currentRefreshStep > 0) {
currentRefreshStep--;
if (currentRefreshStep == 0 ) {
currentRefreshStep = refreshStep;
return true;
}
}
return false;
}
public Collection<? extends Reg> getRegs() {
return Arrays.asList(reg1);
}
public Reg getReg1() {
return reg1;
}
/**
* Prepare standard toString for config.
*
* @return new pre filed StringBuilder.
*/
protected String toString(StringBuilder str) {
StringBuilder sb = new StringBuilder();
sb.append(getClass().getSimpleName()).append("[");
sb.append("slave=").append(slaveName);
sb.append(", name=").append(itemName);
sb.append(", reg=").append(reg1);
if (str != null) {
sb.append(str);
}
if (refreshStep != 1) {
sb.append(", refreshStep=").append(refreshStep);
}
sb.append("]");
return sb.toString();
}
/**
* Looking for paramsName=value in config items list.
*
* @param confItems
* @param param
* param name to look for value
* @return value or defaultValue if property not found
*/
protected String getParamsFromConf(List<String> confItems, String param, String defaultValue) {
for (Iterator<String> iterator = confItems.iterator(); iterator.hasNext();) {
String conf = iterator.next();
Matcher matcher = PARAM_CONFIG_PATTERN.matcher(conf);
if (matcher.find()) {
if (StringUtils.equalsIgnoreCase(matcher.group(1), param)) {
iterator.remove();
return matcher.group(2);
}
}
}
return defaultValue;
}
protected int getParamsFromConfAsInt(List<String> confItems, String param, int defaultValue) throws BindingConfigParseException {
String strParam = getParamsFromConf(confItems, param, String.valueOf(defaultValue));
try {
return Integer.parseInt(strParam);
} catch (NumberFormatException e) {
throw new BindingConfigParseException(e.getMessage());
}
}
public abstract State getState(Map<Reg, RegValue> response);
public void command(FatekPLC fatekPLC, Command command) throws CommandException {
throw new UnsupportedCommandException(this, command);
}
}