/**
* 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.io.transport.cul.internal.serial;
import java.util.Arrays;
import java.util.Collections;
import java.util.Dictionary;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.apache.commons.lang.StringUtils;
import org.openhab.io.transport.cul.CULMode;
import org.openhab.io.transport.cul.internal.CULConfig;
import org.openhab.io.transport.cul.internal.CULConfigFactory;
import org.osgi.service.cm.ConfigurationException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import gnu.io.SerialPort;
/**
* Configuration factory for serial device handler implementation.
*
* @author Patrick Ruckstuhl
* @since 1.9.0
*/
public class CULSerialConfigFactory implements CULConfigFactory {
private final static Logger logger = LoggerFactory.getLogger(CULSerialConfigFactory.class);
private static final Map<String, Integer> validParitiesMap;
private static final List<Integer> validBaudrateMap;
static {
Map<String, Integer> parities = new HashMap<String, Integer>();
parities.put("EVEN", SerialPort.PARITY_EVEN);
parities.put("ODD", SerialPort.PARITY_ODD);
parities.put("MARK", SerialPort.PARITY_MARK);
parities.put("NONE", SerialPort.PARITY_NONE);
parities.put("SPACE", SerialPort.PARITY_SPACE);
validParitiesMap = Collections.unmodifiableMap(parities);
Integer baudrates[] = { 75, 110, 300, 1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200 };
validBaudrateMap = Collections.unmodifiableList(Arrays.asList(baudrates));
}
private final static String KEY_BAUDRATE = "baudrate";
private final static String KEY_PARITY = "parity";
@Override
public CULConfig create(String deviceType, String deviceAddress, CULMode mode, Dictionary<String, ?> config)
throws ConfigurationException {
int baudRate = 9600;
final String configuredBaudRate = (String) config.get(KEY_BAUDRATE);
Integer tmpBaudRate = baudrateFromConfig(configuredBaudRate);
if (tmpBaudRate != null) {
baudRate = tmpBaudRate;
logger.info("Update config, {} = {}", KEY_BAUDRATE, baudRate);
}
int parityMode = SerialPort.PARITY_EVEN;
final String configuredParity = (String) config.get(KEY_PARITY);
Integer parsedParityNumber = parityFromConfig(configuredParity);
if (parsedParityNumber != null) {
parityMode = parsedParityNumber;
logger.info("Update config, {} = {} ({})", KEY_PARITY, convertParityModeToString(parityMode), parityMode);
}
return new CULSerialConfig(deviceType, deviceAddress, mode, baudRate, parityMode);
}
private Integer parityFromConfig(final String configuredParity) {
if (StringUtils.isNotBlank(configuredParity)) {
try {
if (isValidParity(configuredParity)) {
return validParitiesMap.get(configuredParity.toUpperCase());
} else { // allow literal parity assignment?
int parsedParityNumber = Integer.parseInt(configuredParity);
if (isValidParity(parsedParityNumber)) {
return parsedParityNumber;
} else {
logger.error("The configured '{}' value is invalid. The value '{}' has to be one of {}.",
KEY_PARITY, parsedParityNumber, validParitiesMap.keySet());
}
}
} catch (NumberFormatException e) {
logger.error("Error parsing config key '{}'. Use one of {}.", KEY_PARITY, validParitiesMap.keySet());
}
}
return null;
}
/**
* calculate baudrate from config String
*
* @param configuredBaudRate
* @return baud Rate or null if failed
*/
private Integer baudrateFromConfig(final String configuredBaudRate) {
if (StringUtils.isNotBlank(configuredBaudRate)) {
try {
int tmpBaudRate = Integer.parseInt(configuredBaudRate);
if (validBaudrateMap.contains(tmpBaudRate)) {
return tmpBaudRate;
} else {
logger.error(
"Error parsing config parameter '{}'. Value = {} is not a valid baudrate. Value must be in [75, 110, 300, 1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200]",
KEY_BAUDRATE, tmpBaudRate);
}
} catch (NumberFormatException e) {
logger.error("Error parsing config parameter '{}' to integer. Value = {}", KEY_BAUDRATE,
configuredBaudRate);
}
}
return null;
}
/**
* Checks if mode is a valid input for 'SerialPort' - class
*
* @param mode
* @return true if valid
*/
private boolean isValidParity(int mode) {
return validParitiesMap.containsValue(mode);
}
/**
* Checks if mode is a valid input for 'SerialPort' - class
*
* @param mode
* @return true if valid
*/
private boolean isValidParity(String mode) {
return validParitiesMap.containsKey(mode.toUpperCase());
}
/**
* converts modes integer representation into a readable sting
*
* @param mode
* @return text if mode was valid, otherwise "invalid mode"
*/
private String convertParityModeToString(int mode) {
if (validParitiesMap.containsValue(mode)) {
for (Entry<String, Integer> parity : validParitiesMap.entrySet()) {
if (parity.getValue().equals(mode)) {
return parity.getKey();
}
}
}
return "invalid mode";
}
}