org.openhab.binding.ebus.internal.EBusBinding.java Source code

Java tutorial

Introduction

Here is the source code for org.openhab.binding.ebus.internal.EBusBinding.java

Source

/**
 * 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.ebus.internal;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Dictionary;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.commons.lang.StringUtils;
import org.openhab.binding.ebus.EBusBindingProvider;
import org.openhab.binding.ebus.internal.connection.AbstractEBusConnector;
import org.openhab.binding.ebus.internal.connection.EBusCommandProcessor;
import org.openhab.binding.ebus.internal.connection.EBusConnectorEventListener;
import org.openhab.binding.ebus.internal.connection.EBusSerialConnector;
import org.openhab.binding.ebus.internal.connection.EBusTCPConnector;
import org.openhab.binding.ebus.internal.parser.EBusConfigurationProvider;
import org.openhab.binding.ebus.internal.parser.EBusTelegramParser;
import org.openhab.binding.ebus.internal.utils.EBusUtils;
import org.openhab.binding.ebus.internal.utils.StateUtils;
import org.openhab.core.binding.AbstractBinding;
import org.openhab.core.types.Command;
import org.openhab.core.types.State;
import org.osgi.service.cm.Configuration;
import org.osgi.service.cm.ConfigurationAdmin;
import org.osgi.service.cm.ConfigurationException;
import org.osgi.service.cm.ManagedService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * eBus binding implementation.
 * 
 * @author Christian Sowada
 * @since 1.7.0
 */
public class EBusBinding extends AbstractBinding<EBusBindingProvider>
        implements ManagedService, EBusConnectorEventListener {

    private static final Logger logger = LoggerFactory.getLogger(EBusBinding.class);

    // Used to process the commands incl. polling
    private EBusCommandProcessor commandProcessor;

    // The connector to serial or ethernet
    private AbstractEBusConnector connector;

    // The parser to converts received bytes to key/value maps
    private EBusTelegramParser parser;

    // Used to check binding configuration
    private ConfigurationAdmin configurationAdminService;

    // 
    private EBusConfigurationProvider configurationProvider;

    /* (non-Javadoc)
     * @see org.openhab.core.binding.AbstractBinding#internalReceiveCommand(java.lang.String, org.openhab.core.types.Command)
     */
    @Override
    protected void internalReceiveCommand(String itemName, Command command) {

        final String type = command.toString().toLowerCase();

        for (EBusBindingProvider provider : providers) {
            byte[] data = commandProcessor.composeSendData(provider, itemName, type);

            connector.send(data);
        }
    }

    /**
     * Set the OSGI Admin Service
     * @param configurationAdminService
     */
    public void setConfigurationAdmin(ConfigurationAdmin configurationAdminService) {
        this.configurationAdminService = configurationAdminService;
    }

    /**
     * Unset the OSGI Admin Service
     * @param configurationAdminService
     */
    public void unsetConfigurationAdmin(ConfigurationAdmin configurationAdminService) {
        this.configurationAdminService = null;
    }

    /**
     * Check and initialize if needed the configuration provider
     */
    private void checkConfigurationProvider() {
        if (configurationProvider == null)
            configurationProvider = new EBusConfigurationProvider();
    }

    /* (non-Javadoc)
     * @see org.osgi.service.cm.ManagedService#updated(java.util.Dictionary)
     */
    @Override
    public void updated(Dictionary<String, ?> properties) throws ConfigurationException {

        logger.info("Update eBus Binding configuration ...");

        try {
            // stop last thread if active
            if (connector != null && connector.isAlive()) {
                connector.interrupt();
            }

            // check to ensure that it is available
            checkConfigurationProvider();

            // clear current configuration
            configurationProvider.clear();

            // load parser from default url
            parser = new EBusTelegramParser(configurationProvider);

            URL configurationUrl = null;
            String parsers = (String) properties.get("parsers");

            if (StringUtils.isEmpty(parsers)) {
                // set to current stable configurations as default
                parsers = "common,wolf";
            }

            for (String elem : parsers.split(",")) {
                configurationUrl = null;

                // check for keyword custom to load custom configuration
                if (elem.trim().equals("custom")) {
                    String parserUrl = (String) properties.get("parserUrl");
                    if (parserUrl != null) {
                        logger.debug("Load custom eBus Parser with url {}", parserUrl);
                        configurationUrl = new URL(parserUrl);
                    }

                } else {
                    logger.debug("Load eBus Parser Configuration \"{}\" ...", elem.trim());
                    configurationUrl = this.getClass().getResource("/" + elem.trim() + "-configuration.json");
                }

                if (configurationUrl != null) {
                    configurationProvider.loadConfigurationFile(configurationUrl);
                }
            }

            // check minimal config
            if (properties.get("serialPort") != null && properties.get("hostname") != null) {
                throw new ConfigurationException("hostname", "Set property serialPort or hostname, not both!");
            }

            if (StringUtils.isNotEmpty((String) properties.get("serialPort"))) {

                // use the serial connector
                connector = new EBusSerialConnector((String) properties.get("serialPort"));

            } else if (StringUtils.isNotEmpty((String) properties.get("hostname"))) {

                // use the tcp-ip connector
                connector = new EBusTCPConnector((String) properties.get("hostname"),
                        Integer.parseInt((String) properties.get("port")));
            }

            // Set eBus sender id or default 0xFF
            if (StringUtils.isNotEmpty((String) properties.get("senderId"))) {
                connector.setSenderId(EBusUtils.toByte((String) properties.get("senderId")));
            }

            // add event listener
            connector.addEBusEventListener(this);

            // start thread
            connector.start();

            // set the new connector
            commandProcessor.setConnector(connector);
            commandProcessor.setConfigurationProvider(configurationProvider);

        } catch (MalformedURLException e) {
            logger.error(e.toString(), e);
        } catch (IOException e) {
            throw new ConfigurationException("general", e.toString(), e);
        }
    }

    /* (non-Javadoc)
     * @see org.openhab.core.binding.AbstractBinding#addBindingProvider(org.openhab.core.binding.BindingProvider)
     */
    @Override
    public void addBindingProvider(EBusBindingProvider provider) {
        super.addBindingProvider(provider);

        if (commandProcessor == null) {
            commandProcessor = new EBusCommandProcessor();
            commandProcessor.setConfigurationProvider(configurationProvider);
        }

        if (provider.providesBinding()) {
            // items already processed, so too late for this listener. do it manually
            commandProcessor.allBindingsChanged(provider);
        }

        provider.addBindingChangeListener(commandProcessor);
    }

    /* (non-Javadoc)
     * @see org.openhab.core.binding.AbstractBinding#removeBindingProvider(org.openhab.core.binding.BindingProvider)
     */
    @Override
    public void removeBindingProvider(EBusBindingProvider provider) {
        super.removeBindingProvider(provider);
        provider.removeBindingChangeListener(commandProcessor);
    }

    /* (non-Javadoc)
     * @see org.openhab.core.binding.AbstractBinding#activate()
     */
    public void activate() {
        super.activate();
        logger.debug("eBus binding has been started.");

        // check to ensure that it is available
        checkConfigurationProvider();

        // observe connection, if not started 15 sec. later than start it manually
        // replacing a bundle doesn't recall update function, more 
        // a bug/enhancement in openhab
        new Thread() {
            @Override
            public void run() {

                try {
                    sleep(15000);

                    if (connector == null) {
                        logger.warn("eBus connector still not started, started it yet!");

                        Configuration configuration = configurationAdminService.getConfiguration("org.openhab.ebus",
                                null);
                        if (configuration != null) {
                            updated(configuration.getProperties());

                            for (EBusBindingProvider provider : EBusBinding.this.providers) {
                                commandProcessor.allBindingsChanged(provider);
                            }
                        }
                    }

                } catch (InterruptedException e) {
                    logger.error(e.toString(), e);
                } catch (ConfigurationException e) {
                    logger.error(e.toString(), e);
                } catch (IOException e) {
                    logger.error(e.toString(), e);
                }

            }
        }.start();
        ;

    }

    /* (non-Javadoc)
     * @see org.openhab.core.binding.AbstractBinding#deactivate()
     */
    public void deactivate() {
        super.deactivate();

        logger.debug("eBus binding has been stopped.");

        if (connector != null && connector.isAlive()) {
            connector.interrupt();
            connector = null;
        }

        if (commandProcessor != null) {
            commandProcessor.deactivate();
            commandProcessor = null;
        }
    }

    /* (non-Javadoc)
     * @see org.openhab.binding.ebus.connection.EBusConnectorEventListener#onTelegramReceived(org.openhab.binding.ebus.EbusTelegram)
     */
    @Override
    public void onTelegramReceived(EBusTelegram telegram) {

        // parse the raw telegram to a key/value map
        final Map<String, Object> results = parser.parse(telegram);

        if (results == null) {
            logger.debug("No valid parser result for raw telegram!");
            return;
        }

        for (Entry<String, Object> entry : results.entrySet()) {

            State state = StateUtils.convertToState(entry.getValue());

            // process if the state is set
            if (state != null) {

                // loop over all items to update the state
                for (EBusBindingProvider provider : providers) {
                    for (String itemName : provider.getItemNames(entry.getKey())) {

                        Byte telegramSource = provider.getTelegramSource(itemName);
                        Byte telegramDestination = provider.getTelegramDestination(itemName);

                        // check if this item has a src or dst defined
                        if (telegramSource == null || telegram.getSource() == telegramSource) {
                            if (telegramDestination == null || telegram.getDestination() == telegramDestination) {
                                eventPublisher.postUpdate(itemName, state);
                            }
                        }
                    }
                } // for
            } // if
        }
    }

}