Java tutorial
/** * Copyright (c) 2010-2015, 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.echonetlite.internal; import org.apache.commons.lang3.StringUtils; import org.openhab.binding.echonetlite.ECHONETLiteBindingProvider; import org.openhab.core.binding.BindingConfig; 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.StringType; import org.openhab.core.transform.TransformationException; import org.openhab.core.transform.TransformationHelper; import org.openhab.core.transform.TransformationService; import org.openhab.core.types.Command; import org.openhab.core.types.TypeParser; import org.openhab.model.item.binding.AbstractGenericBindingProvider; import org.openhab.model.item.binding.BindingConfigParseException; import org.osgi.framework.BundleContext; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * This class is responsible for parsing the binding configuration. * <p> * Example configuration: * </p> * * * * Example items: * * <pre> * Switch AirconditionerSwitch AirConditionerSwitch? { echonetlite="aircon1:ON:01300105FF016101800130" } * </pre> * * * @author aklevy, Kazuhiro Matsuda * @since 1.8.0 */ public class ECHONETLiteGenericBindingProvider extends AbstractGenericBindingProvider implements ECHONETLiteBindingProvider { static final Logger logger = LoggerFactory.getLogger(ECHONETLiteGenericBindingProvider.class); /* * Artificial command for the echonetlite-in configuration */ protected static final Command IN_BINDING_KEY = StringType.valueOf("IN_BINDING"); /* * Artificial command for the echonetlite-out configuration */ protected static final Command OUT_BINDING_KEY = StringType.valueOf("OUT_BINDING"); protected static final Command OUT_BINDING_FOR_UPDATE_KEY = StringType.valueOf("OUT_BINDING_FOR_UPDATE_KEY"); protected static final Command IN_BINDING_FOR_UPDATE_KEY = StringType.valueOf("IN_BINDING_FOR_UPDATE_KEY"); protected static final Command CHANGED_COMMAND_KEY = StringType.valueOf("CHANGED"); protected static final Command WILDCARD_COMMAND_KEY = StringType.valueOf("*"); private long refreshInterval = 60000; /** {@link pattern} which mathes a binding configuration part */ private static final Pattern BASE_CONFIG_PATTERN = Pattern.compile("([<|>|\\*]\\[.*?\\])*"); /** {@link Pattern* which matches an In-Binding */ private static final Pattern IN_BINDING_PATTERN = Pattern .compile("<\\[([0-9_a-zA-Z]+):([0-9_a-zA-Z]+):([0-9_a-zA-Z]+)\\]"); private static final Pattern IN_BINDING_PATTERN_REFRESH = Pattern .compile("<\\[([0-9_a-zA-Z]+):([0-9_a-zA-Z]+):([0-9_a-zA-Z]+):([0-9]+)\\]"); private static final Pattern IN_BINDING_PATTERN_WO_COMMAND = Pattern .compile("<\\[([0-9_a-zA-Z]+):([0-9_a-zA-Z]+)\\]"); private static final Pattern IN_BINDING_PATTERN_WO_COMMAND_REFRESH = Pattern .compile("<\\[([0-9_a-zA-Z]+):([0-9_a-zA-Z]+):([0-9]+)\\]"); private static final Pattern OUT_BINDING_PATTERN = Pattern .compile(">\\[([0-9_a-zA-Z]+):([0-9_a-zA-Z]+):([0-9_a-zA-Z]+):([0-9_a-zA-Z]+)\\]"); private static final Pattern OUT_BINDING_PATTERN_WO_COMMAND = Pattern .compile(">\\[([0-9_a-zA-Z]+):([0-9_a-zA-Z]+)\\]"); /** * {@inheritDoc} */ public String getBindingType() { return "echonetlite"; } /** * {@inheritDoc */ @Override public void validateItemType(Item item, String bindingConfig) throws BindingConfigParseException { if (!(item instanceof StringItem || item instanceof NumberItem || item instanceof SwitchItem)) { throw new BindingConfigParseException("Item '" + item.getName() + "' is of type '" + item.getClass().getSimpleName() + "', only StringItems, NumberItems and SwitchItems are allowed - please check your *.items configuration"); } } /** * {@inheritDoc} */ @Override public void processBindingConfiguration(String context, Item item, String bindingConfig) throws BindingConfigParseException { super.processBindingConfiguration(context, item, bindingConfig); if (bindingConfig != null) { ECHONETLiteBindingConfig newConfig = new ECHONETLiteBindingConfig(); Matcher matcher = BASE_CONFIG_PATTERN.matcher(bindingConfig); if (!matcher.matches()) { throw new BindingConfigParseException( "bindingConfig '" + bindingConfig + "' doesn't contain a valid binding configuration"); } matcher.reset(); while (matcher.find()) { String bindingConfigPart = matcher.group(1); if (StringUtils.isNotBlank(bindingConfigPart)) { parseBindingConfig(newConfig, item, bindingConfigPart); } } addBindingConfig(item, newConfig); } else { logger.warn("bindingConfig is NULL (item=" + item + ") -> processing bindingConfig aborted!"); } } private void parseBindingConfig(ECHONETLiteBindingConfig config, Item item, String bindingConfig) throws BindingConfigParseException { config.itemType = item.getClass(); if (bindingConfig != null) { Matcher inMatcher = IN_BINDING_PATTERN.matcher(bindingConfig); if (!inMatcher.matches()) { inMatcher = IN_BINDING_PATTERN_REFRESH.matcher(bindingConfig); } if (inMatcher.matches()) { ECHONETLiteBindingConfigElement newElement = new ECHONETLiteBindingConfigElement(); newElement.deviceId = inMatcher.group(1).toString(); newElement.epc = inMatcher.group(2).toString(); if (inMatcher.groupCount() == 3) newElement.refreshInterval = Integer.valueOf(inMatcher.group(3)).intValue(); logger.debug("item:{} newElement:{}", item, newElement); config.put(IN_BINDING_KEY, newElement); } else { inMatcher = IN_BINDING_PATTERN_WO_COMMAND.matcher(bindingConfig); if (inMatcher.matches()) { ECHONETLiteBindingConfigElement newElement = new ECHONETLiteBindingConfigElement(); newElement.deviceId = inMatcher.group(1).toString(); newElement.epc = inMatcher.group(2).toString(); newElement.refreshInterval = refreshInterval; logger.debug("item:{} in_binding_update_newElement:{}", item, newElement); config.put(IN_BINDING_FOR_UPDATE_KEY, newElement); } } Matcher outMatcher = OUT_BINDING_PATTERN.matcher(bindingConfig); if (outMatcher.matches()) { ECHONETLiteBindingConfigElement newElement = new ECHONETLiteBindingConfigElement(); Command command = createCommandFromString(item, outMatcher.group(1)); newElement.deviceId = outMatcher.group(2).toString(); newElement.epc = outMatcher.group(3).toString(); newElement.edt = outMatcher.group(4).toString(); logger.debug("item:{} newElement:{}", item, newElement); config.put(command, newElement); } else { outMatcher = OUT_BINDING_PATTERN_WO_COMMAND.matcher(bindingConfig); if (outMatcher.matches()) { ECHONETLiteBindingConfigElement newElement = new ECHONETLiteBindingConfigElement(); newElement.deviceId = outMatcher.group(1).toString(); newElement.epc = outMatcher.group(2).toString(); logger.debug("item:{} out_binding_update_newElement:{}", item, newElement); config.put(OUT_BINDING_FOR_UPDATE_KEY, newElement); } } if (!inMatcher.matches() && !outMatcher.matches()) { throw new BindingConfigParseException( getBindingType() + "binding configuration must consist of two/three [config=" + inMatcher + "] of four parts [config=" + outMatcher + "]"); } } else { return; } } /** * {@inheritDoc} */ public List<String> getInBindingItemNames() { List<String> inBindings = new ArrayList<String>(); for (String itemName : bindingConfigs.keySet()) { ECHONETLiteBindingConfig ECHONETLiteConfig = (ECHONETLiteBindingConfig) bindingConfigs.get(itemName); if (ECHONETLiteConfig.containsKey(IN_BINDING_KEY)) { inBindings.add(itemName); } } return inBindings; } /** * {@inheritDoc} */ public List<String> getOutBindingItemNames() { List<String> outBindings = new ArrayList<String>(); for (String itemName : bindingConfigs.keySet()) { ECHONETLiteBindingConfig ECHONETLiteConfig = (ECHONETLiteBindingConfig) bindingConfigs.get(itemName); if (ECHONETLiteConfig.containsKey(OUT_BINDING_KEY)) { outBindings.add(itemName); } } return outBindings; } /** * {@inheritDoc */ @Override public Class<? extends Item> getItemType(String itemName) { ECHONETLiteBindingConfig config = (ECHONETLiteBindingConfig) bindingConfigs.get(itemName); return config != null ? config.itemType : null; } static class ECHONETLiteBindingConfig extends HashMap<Command, ECHONETLiteBindingConfigElement> implements BindingConfig { private static final long serialVersionUID = 4697146075427676117L; Class<? extends Item> itemType; } static class ECHONETLiteBindingConfigElement implements BindingConfig { public String command; public String deviceId; public String epc; public String edt; public String value; public long refreshInterval; public TransformationService transformationService; public String transformationName; public String transformationParam; @Override public String toString() { return "ECHONETLiteConfigElement [deviceId=" + deviceId + ", epc=" + epc + ", edt=" + edt + ", refreshInterval=" + refreshInterval + "]"; } public boolean setTransformationRule(String rule) { int pos = rule.indexOf('('); if (pos == -1) return false; // split the transformation rule into name and param. transformationName = rule.substring(0, pos); transformationParam = rule.substring(pos + 1, rule.length() - 1); BundleContext context = ECHONETLiteActivator.getContext(); //get the transfpormation service transformationService = TransformationHelper.getTransformationService(context, transformationName); if (transformationService == null) { logger.debug("No transfromation service found for {}", transformationName); return false; } return true; } public String doTransformation(String value) throws TransformationException { if (transformationService == null) return value; return transformationService.transform(transformationParam, value); } } @Override public String doTransformation(String itemName, String value) throws TransformationException { ECHONETLiteBindingConfig config = (ECHONETLiteBindingConfig) bindingConfigs.get(itemName); if (config == null) return value; if (config.get(IN_BINDING_KEY) == null) return value; return config.get(IN_BINDING_KEY).doTransformation(value); } @Override public String getDeviceId(String itemName) { ECHONETLiteBindingConfig config = (ECHONETLiteBindingConfig) bindingConfigs.get(itemName); return config != null ? config.get(IN_BINDING_KEY).deviceId : new String(""); } @Override public String getDeviceId(String itemName, Command command) { ECHONETLiteBindingConfig config = (ECHONETLiteBindingConfig) bindingConfigs.get(itemName); //return config != null ? config.get(command).deviceId : new String(""); if (config != null) { if (config.get(command) != null) { return config.get(command).deviceId; } else { return config.get(OUT_BINDING_FOR_UPDATE_KEY).deviceId; } } else { return new String(""); } } @Override public String getEpc(String itemName) { ECHONETLiteBindingConfig config = (ECHONETLiteBindingConfig) bindingConfigs.get(itemName); return config != null ? config.get(IN_BINDING_KEY).epc : new String(""); } @Override public String getEpc(String itemName, Command command) { ECHONETLiteBindingConfig config = (ECHONETLiteBindingConfig) bindingConfigs.get(itemName); //return config != null ? config.get(command).epc : new String(""); if (config != null) { if (config.get(command) != null) { return config.get(command).epc; } else { return config.get(OUT_BINDING_FOR_UPDATE_KEY).epc; } } else { return new String(""); } } @Override public String getEdt(String itemName) { ECHONETLiteBindingConfig config = (ECHONETLiteBindingConfig) bindingConfigs.get(itemName); return config != null ? config.get(IN_BINDING_KEY).edt : new String(""); } @Override public String getEdt(String itemName, Command command) { ECHONETLiteBindingConfig config = (ECHONETLiteBindingConfig) bindingConfigs.get(itemName); //return config != null ? config.get(command).edt : new String(""); if (config != null) { if (config.get(command) != null) { return config.get(command).edt; } else { return StringUtils.substringAfter(command.toString(), "value="); } } else { return new String(""); } } @Override public String getValue(String itemName, Command command) { ECHONETLiteBindingConfig config = (ECHONETLiteBindingConfig) bindingConfigs.get(itemName); //return config != null ? config.get(command).value : null; if (config != null) { if (config.get(command) != null) { return config.get(command).edt; } else { return StringUtils.substringAfter(command.toString(), "value="); } } else { return new String(""); } } @Override public String getOutputStateDeviceId(String itemName) { ECHONETLiteBindingConfig config = (ECHONETLiteBindingConfig) bindingConfigs.get(itemName); ECHONETLiteBindingConfigElement outSetting = getOutSetting(config); return outSetting != null ? outSetting.deviceId : null; } @Override public String getInputStateDeviceId(String itemName) { ECHONETLiteBindingConfig config = (ECHONETLiteBindingConfig) bindingConfigs.get(itemName); ECHONETLiteBindingConfigElement inSetting = getInSetting(config); return inSetting != null ? inSetting.deviceId : null; } @Override public String getOutputStateEpc(String itemName) { ECHONETLiteBindingConfig config = (ECHONETLiteBindingConfig) bindingConfigs.get(itemName); ECHONETLiteBindingConfigElement outSetting = getOutSetting(config); return config != null ? outSetting.epc : new String(""); } @Override public String getInputStateEpc(String itemName) { ECHONETLiteBindingConfig config = (ECHONETLiteBindingConfig) bindingConfigs.get(itemName); ECHONETLiteBindingConfigElement inSetting = getInSetting(config); return config != null ? inSetting.epc : new String(""); } private ECHONETLiteBindingConfigElement getOutSetting(ECHONETLiteBindingConfig config) { ECHONETLiteBindingConfigElement outSetting = null; if (config != null) { outSetting = config.get(OUT_BINDING_FOR_UPDATE_KEY); } return outSetting; } private ECHONETLiteBindingConfigElement getInSetting(ECHONETLiteBindingConfig config) { ECHONETLiteBindingConfigElement inSetting = null; if (config != null) { inSetting = config.get(IN_BINDING_FOR_UPDATE_KEY); } return inSetting; } public long getRefreshInterval(String itemName) { ECHONETLiteBindingConfig config = (ECHONETLiteBindingConfig) bindingConfigs.get(itemName); return config != null && config.get(IN_BINDING_KEY) != null ? config.get(IN_BINDING_KEY).refreshInterval : 0; } private Command createCommandFromString(Item item, String commandAsString) throws BindingConfigParseException { if (CHANGED_COMMAND_KEY.equals(commandAsString)) { return CHANGED_COMMAND_KEY; } else if (WILDCARD_COMMAND_KEY.equals(commandAsString)) { return WILDCARD_COMMAND_KEY; } else { Command command = TypeParser.parseCommand(item.getAcceptedCommandTypes(), commandAsString); if (command == null) { throw new BindingConfigParseException("could not create Command from '" + commandAsString + "' "); } return command; } } }