org.openhab.binding.pca301.internal.PCA301Binding.java Source code

Java tutorial

Introduction

Here is the source code for org.openhab.binding.pca301.internal.PCA301Binding.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.pca301.internal;

import java.util.Dictionary;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.openhab.binding.pca301.PCA301BindingProvider;
import org.openhab.binding.pca301.internal.PCA301BindingConfig.Property;
import org.openhab.binding.pca301.internal.jeelink.JeeLinkDevice;
import org.openhab.binding.pca301.internal.jeelink.JeeLinkListener;
import org.openhab.core.binding.AbstractBinding;
import org.openhab.core.library.types.DecimalType;
import org.openhab.core.library.types.OnOffType;
import org.openhab.core.types.Command;
import org.openhab.core.types.State;
import org.osgi.service.cm.ConfigurationException;
import org.osgi.service.cm.ManagedService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Binding class which connects openHAB with PCA301 devices.
 * 
 * @author ribbeck
 * @since 1.7.2
 */
public class PCA301Binding extends AbstractBinding<PCA301BindingProvider>
        implements ManagedService, JeeLinkListener {

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

    private final static String KEY_PORT = "port";
    private final static String KEY_RETRY_COUNT = "retryCount";

    private final Map<Integer, Integer> channels = new HashMap<Integer, Integer>();

    private final Map<String, State> cache = new HashMap<String, State>();

    JeeLinkDevice device = null;

    @Override
    public void activate() {
        logger.trace("activate() called");
        if (device != null) {
            device.open();
        }
    }

    @Override
    public void deactivate() {
        logger.trace("deactivate() called");
        if (device != null) {
            device.close();
        }
    }

    /**
     * @{inheritDoc
     */
    @Override
    protected void internalReceiveCommand(String itemName, Command command) {

        logger.trace("internalReceiveCommand(" + itemName + ", " + command + ") called");
        if (command instanceof OnOffType) {

            final OnOffType switchValue = (OnOffType) command;
            executeCommand(itemName, switchValue == OnOffType.ON);
        }
    }

    /**
     * @{inheritDoc
     */
    @Override
    protected void internalReceiveUpdate(String itemName, State newState) {

        logger.trace("internalReceiveUpdate(" + itemName + ", " + newState + ") called");
        if (newState instanceof OnOffType) {

            final OnOffType switchValue = (OnOffType) newState;
            executeCommand(itemName, switchValue == OnOffType.ON);
        }
    }

    private void executeCommand(String itemName, boolean value) {

        for (PCA301BindingProvider provider : providers) {

            // find address and channel of item
            final int address = provider.getAddress(itemName);
            if (address != 0) {
                Integer channel = null;
                synchronized (channels) {
                    channel = channels.get(Integer.valueOf(address));
                }

                if (channel == null) {
                    logger.warn("Unknown address: " + String.valueOf(address));
                    return;
                }

                // get property
                final String propertyName = provider.getProperty(itemName);
                if (propertyName == null) {
                    logger.error("Cannot find property of item " + itemName);
                    return;
                }

                logger.trace("Send " + propertyName + " to address=" + address + ", channnel=" + channel);

                Property property = Property.UNKNOWN;
                try {
                    property = Property.valueOf(propertyName.toUpperCase());

                } catch (IllegalArgumentException e) {
                    logger.error("Unknown property: " + propertyName);
                    return;
                }

                // send command
                if (device != null) {

                    switch (property) {
                    case RESET:
                        if (value) {
                            device.resetConsumption(address, channel);
                        }
                        break;
                    case STATE:
                        device.setState(address, channel, value);
                        break;
                    default:
                        logger.warn("Invalid property: " + propertyName);
                        break;
                    }

                }
            }
        }
    }

    /**
     * @{inheritDoc
     */
    public void updated(Dictionary<String, ?> config) throws ConfigurationException {
        logger.debug("Received new config");
        if (config != null) {

            // configuration has changed, close JeeLink device if necessary
            if (device != null) {

                if (device.isOpen()) {
                    device.close();
                }
                device.removeListener(this);
                device = null;
            }

            // reset channels and cache
            synchronized (channels) {
                channels.clear();
            }
            synchronized (cache) {
                cache.clear();
            }

            // read serial port name
            final String port = (String) config.get(KEY_PORT);
            if (StringUtils.isBlank(port)) {
                logger.error("Port of JeeLink device is missing");
                throw new ConfigurationException(KEY_PORT, "The port can't be empty");
            }

            // read retry count, default is zero
            int retryCount = 0;
            final String retryCountValue = (String) config.get(KEY_RETRY_COUNT);
            if (StringUtils.isNotBlank(retryCountValue)) {
                try {
                    retryCount = Integer.parseInt(retryCountValue);

                } catch (final NumberFormatException e) {
                    logger.error("Failed to read retry count value: " + retryCountValue, e);
                }
            }

            // create and open JeeLink device
            device = new JeeLinkDevice(port, retryCount);
            device.addListener(this);
            device.open();
        }
    }

    @Override
    public void onStateReceived(int address, int channel, boolean state) {

        synchronized (channels) {
            channels.put(Integer.valueOf(address), Integer.valueOf(channel));
        }

        logger.debug("Received for " + String.valueOf(address) + " state=" + (state ? "on" : "off"));
        publishUpdate(address, Property.STATE, state ? OnOffType.ON : OnOffType.OFF);
    }

    @Override
    public void onValuesReceived(int address, int channel, double power, double consumption) {

        synchronized (channels) {
            channels.put(Integer.valueOf(address), Integer.valueOf(channel));
        }

        final String powerValue = Double.toString(power);
        final String consumptionValue = Double.toString(consumption);

        logger.debug("Received for " + String.valueOf(address) + " power=" + powerValue + " and consumption="
                + consumptionValue);
        publishUpdate(address, Property.POWER, DecimalType.valueOf(powerValue));
        publishUpdate(address, Property.CONSUMPTION, DecimalType.valueOf(consumptionValue));
    }

    /**
     * Sends an update event to openHAB for passed value if necessary.
     * @param address PCA301 device address
     * @param property PCA301 property
     * @param newValue new value of property
     */
    private void publishUpdate(int address, Property property, State newValue) {

        for (PCA301BindingProvider provider : providers) {

            // check if item exists for passed property
            final String itemName = provider.getItemName(address, property.toString());
            if (itemName != null) {

                // get and refresh current state
                State currentValue = null;
                synchronized (cache) {
                    currentValue = cache.put(itemName, newValue);
                }

                if (!newValue.equals(currentValue)) {
                    // value has changed
                    eventPublisher.postUpdate(itemName, newValue);
                }
            }
        }
    }
}