Search in sources :

Example 1 with EndpointPoolConfiguration

use of org.openhab.binding.modbus.internal.pooling.EndpointPoolConfiguration in project openhab1-addons by openhab.

the class ModbusBinding method updated.

@Override
public void updated(Dictionary<String, ?> config) throws ConfigurationException {
    try {
        // remove all known items if configuration changed
        clear();
        reconstructConnectionPool();
        if (config == null) {
            logger.debug("Got null config!");
            return;
        }
        Enumeration<String> keys = config.keys();
        Map<String, EndpointPoolConfiguration> slavePoolConfigs = new HashMap<String, EndpointPoolConfiguration>();
        Map<ModbusSlaveEndpoint, EndpointPoolConfiguration> endpointPoolConfigs = new HashMap<ModbusSlaveEndpoint, EndpointPoolConfiguration>();
        while (keys.hasMoreElements()) {
            final String key = keys.nextElement();
            final String value = (String) config.get(key);
            try {
                // don't want to process here ...
                if ("service.pid".equals(key)) {
                    continue;
                }
                Matcher matcher = EXTRACT_MODBUS_CONFIG_PATTERN.matcher(key);
                if (!matcher.matches()) {
                    if ("poll".equals(key)) {
                        if (StringUtils.isNotBlank((String) config.get(key))) {
                            pollInterval = Integer.valueOf((String) config.get(key));
                        }
                    } else if ("writemultipleregisters".equals(key)) {
                        // XXX: ugly to touch base class but kept here for backwards compat
                        // FIXME: should this be deprecated as introduced as slave specific parameter?
                        ModbusSlave.setWriteMultipleRegisters(Boolean.valueOf(config.get(key).toString()));
                    } else {
                        logger.debug("given modbus-slave-config-key '{}' does not follow the expected pattern or 'serial.<slaveId>.<{}>'", key, VALID_CONFIG_KEYS);
                    }
                    continue;
                }
                matcher.reset();
                matcher.find();
                String slave = matcher.group(2);
                ModbusSlave modbusSlave = modbusSlaves.get(slave);
                EndpointPoolConfiguration endpointPoolConfig = slavePoolConfigs.get(slave);
                if (modbusSlave == null) {
                    if (matcher.group(1).equals(TCP_PREFIX)) {
                        modbusSlave = new ModbusTcpSlave(slave, connectionPool);
                    } else if (matcher.group(1).equals(UDP_PREFIX)) {
                        modbusSlave = new ModbusUdpSlave(slave, connectionPool);
                    } else if (matcher.group(1).equals(SERIAL_PREFIX)) {
                        modbusSlave = new ModbusSerialSlave(slave, connectionPool);
                    } else {
                        throw new ConfigurationException(slave, "the given slave type '" + slave + "' is unknown");
                    }
                    endpointPoolConfig = new EndpointPoolConfiguration();
                    // Do not give up if the connection attempt fails on the first time...
                    endpointPoolConfig.setConnectMaxTries(Modbus.DEFAULT_RETRIES);
                    logger.debug("modbusSlave '{}' instanciated", slave);
                    modbusSlaves.put(slave, modbusSlave);
                }
                String configKey = matcher.group(3);
                if ("connection".equals(configKey)) {
                    String[] chunks = value.split(":");
                    Iterator<String> settingIterator = stringArrayIterator(chunks);
                    if (modbusSlave instanceof ModbusIPSlave) {
                        ((ModbusIPSlave) modbusSlave).setHost(settingIterator.next());
                        //
                        // Defaults for endpoint and slave
                        //
                        modbusSlave.setRetryDelayMillis(DEFAULT_TCP_INTER_TRANSACTION_DELAY_MILLIS);
                        endpointPoolConfig.setPassivateBorrowMinMillis(DEFAULT_TCP_INTER_TRANSACTION_DELAY_MILLIS);
                        //
                        try {
                            ((ModbusIPSlave) modbusSlave).setPort(Integer.valueOf(settingIterator.next()));
                            long passivateBorrowMinMillis = Long.parseLong(settingIterator.next());
                            modbusSlave.setRetryDelayMillis(passivateBorrowMinMillis);
                            endpointPoolConfig.setPassivateBorrowMinMillis(passivateBorrowMinMillis);
                            endpointPoolConfig.setReconnectAfterMillis(Integer.parseInt(settingIterator.next()));
                            // time to wait before trying connect closed connection. Note that
                            // ModbusSlaveConnectionFactoryImpl makes sure that max{passivateBorrowMinMillis, this
                            // parameter} is waited between connection attempts
                            endpointPoolConfig.setInterConnectDelayMillis(Long.parseLong(settingIterator.next()));
                            endpointPoolConfig.setConnectMaxTries(Integer.parseInt(settingIterator.next()));
                            endpointPoolConfig.setConnectTimeoutMillis(Integer.parseInt(settingIterator.next()));
                        } catch (NoSuchElementException e) {
                        // Some of the optional parameters are missing -- it's ok!
                        }
                        if (settingIterator.hasNext()) {
                            String errMsg = String.format("%s Has too many colon (:) separated connection settings for a tcp/udp modbus slave. " + "Expecting at most 6 parameters: hostname (mandatory) and " + "optionally (in this order) port number, " + "interTransactionDelayMillis, reconnectAfterMillis," + "interConnectDelayMillis, connectMaxTries, connectTimeout.", key);
                            throw new ConfigurationException(key, errMsg);
                        }
                    } else if (modbusSlave instanceof ModbusSerialSlave) {
                        SerialParameters serialParameters = new SerialParameters();
                        serialParameters.setPortName(settingIterator.next());
                        //
                        // Defaults for endpoint and slave
                        //
                        // never "disconnect" (close/open serial
                        endpointPoolConfig.setReconnectAfterMillis(-1);
                        // port)
                        // serial connection between borrows
                        modbusSlave.setRetryDelayMillis(DEFAULT_SERIAL_INTER_TRANSACTION_DELAY_MILLIS);
                        endpointPoolConfig.setPassivateBorrowMinMillis(DEFAULT_SERIAL_INTER_TRANSACTION_DELAY_MILLIS);
                        //
                        try {
                            serialParameters.setBaudRate(settingIterator.next());
                            serialParameters.setDatabits(settingIterator.next());
                            serialParameters.setParity(settingIterator.next());
                            serialParameters.setStopbits(settingIterator.next());
                            serialParameters.setEncoding(settingIterator.next());
                            // time to wait between connection passive+borrow, i.e. time to wait between
                            // transactions
                            long passivateBorrowMinMillis = Long.parseLong(settingIterator.next());
                            modbusSlave.setRetryDelayMillis(passivateBorrowMinMillis);
                            endpointPoolConfig.setPassivateBorrowMinMillis(passivateBorrowMinMillis);
                            serialParameters.setReceiveTimeoutMillis(settingIterator.next());
                            serialParameters.setFlowControlIn(settingIterator.next());
                            serialParameters.setFlowControlOut(settingIterator.next());
                        } catch (NoSuchElementException e) {
                        // Some of the optional parameters are missing -- it's ok!
                        }
                        if (settingIterator.hasNext()) {
                            String errMsg = String.format("%s Has too many colon (:) separated connection settings for a serial modbus slave. " + "Expecting at most 9 parameters (got %d): devicePort (mandatory), " + "and 0 or more optional parameters (in this order): " + "baudRate, dataBits, parity, stopBits, " + "encoding, interTransactionWaitMillis, " + "receiveTimeoutMillis, flowControlIn, flowControlOut", key, chunks.length);
                            throw new ConfigurationException(key, errMsg);
                        }
                        ((ModbusSerialSlave) modbusSlave).setSerialParameters(serialParameters);
                    }
                } else if ("start".equals(configKey)) {
                    modbusSlave.setStart(Integer.valueOf(value));
                } else if ("length".equals(configKey)) {
                    modbusSlave.setLength(Integer.valueOf(value));
                } else if ("id".equals(configKey)) {
                    modbusSlave.setId(Integer.valueOf(value));
                } else if ("type".equals(configKey)) {
                    if (ArrayUtils.contains(ModbusBindingProvider.SLAVE_DATA_TYPES, value)) {
                        modbusSlave.setType(value);
                    } else {
                        throw new ConfigurationException(configKey, "the given slave type '" + value + "' is invalid");
                    }
                } else if ("valuetype".equals(configKey)) {
                    if (ArrayUtils.contains(ModbusBindingProvider.VALUE_TYPES, value)) {
                        modbusSlave.setValueType(value);
                    } else {
                        throw new ConfigurationException(configKey, "the given value type '" + value + "' is invalid");
                    }
                } else if ("rawdatamultiplier".equals(configKey)) {
                    modbusSlave.setRawDataMultiplier(Double.valueOf(value.toString()));
                } else if ("updateunchangeditems".equals(configKey)) {
                    modbusSlave.setUpdateUnchangedItems(Boolean.valueOf(value.toString()));
                } else if ("postundefinedonreaderror".equals(configKey)) {
                    modbusSlave.setPostUndefinedOnReadError(Boolean.valueOf(value.toString()));
                } else {
                    throw new ConfigurationException(configKey, "the given configKey '" + configKey + "' is unknown");
                }
                modbusSlaves.put(slave, modbusSlave);
                slavePoolConfigs.put(slave, endpointPoolConfig);
            } catch (Exception e) {
                String errMsg = String.format("Exception when parsing configuration parameter %s = %s  --  %s %s", key, value, e.getClass().getName(), e.getMessage());
                logger.error(errMsg);
                throw new ConfigurationException(key, errMsg);
            }
        }
        // Finally, go through each slave definition, and combine the slave pool configurations
        for (Entry<String, EndpointPoolConfiguration> slaveEntry : slavePoolConfigs.entrySet()) {
            String slave = slaveEntry.getKey();
            EndpointPoolConfiguration poolConfiguration = slaveEntry.getValue();
            ModbusSlaveEndpoint endpoint = modbusSlaves.get(slave).getEndpoint();
            EndpointPoolConfiguration existingPoolConfiguration = endpointPoolConfigs.get(endpoint);
            // Do we have two slaves with same endpoint, but different pool configuration parameters? Warn if we do.
            if (existingPoolConfiguration != null && !existingPoolConfiguration.equals(poolConfiguration)) {
                logger.warn("Slave {} (endpoint {}) has different retry/connection delay " + "(EndpointPoolConfiguration) etc. settings. Replacing {} with {}", slave, endpoint, existingPoolConfiguration, poolConfiguration);
            }
            endpointPoolConfigs.put(endpoint, poolConfiguration);
        }
        connectionFactory.applyEndpointPoolConfigs(endpointPoolConfigs);
        logger.debug("Parsed the following slave->endpoint configurations: {}. If the endpoint is same, " + "connections are shared between the instances.", slavePoolConfigs);
        logger.debug("Parsed the following pool configurations: {}", endpointPoolConfigs);
        logger.debug("config looked good");
        setProperlyConfigured(true);
    } catch (ConfigurationException ce) {
        setProperlyConfigured(false);
        throw ce;
    }
}
Also used : HashMap(java.util.HashMap) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) ModbusSlaveEndpoint(org.openhab.binding.modbus.internal.pooling.ModbusSlaveEndpoint) Matcher(java.util.regex.Matcher) ConfigurationException(org.osgi.service.cm.ConfigurationException) NoSuchElementException(java.util.NoSuchElementException) SerialParameters(net.wimpi.modbus.util.SerialParameters) EndpointPoolConfiguration(org.openhab.binding.modbus.internal.pooling.EndpointPoolConfiguration) ConfigurationException(org.osgi.service.cm.ConfigurationException) NoSuchElementException(java.util.NoSuchElementException)

Aggregations

HashMap (java.util.HashMap)1 NoSuchElementException (java.util.NoSuchElementException)1 ConcurrentHashMap (java.util.concurrent.ConcurrentHashMap)1 Matcher (java.util.regex.Matcher)1 SerialParameters (net.wimpi.modbus.util.SerialParameters)1 EndpointPoolConfiguration (org.openhab.binding.modbus.internal.pooling.EndpointPoolConfiguration)1 ModbusSlaveEndpoint (org.openhab.binding.modbus.internal.pooling.ModbusSlaveEndpoint)1 ConfigurationException (org.osgi.service.cm.ConfigurationException)1