org.openhab.binding.jeelink.internal.JeeLinkBinding.java Source code

Java tutorial

Introduction

Here is the source code for org.openhab.binding.jeelink.internal.JeeLinkBinding.java

Source

/**
 * Copyright (c) 2010-2014, 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.jeelink.internal;

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

import org.apache.commons.lang.StringUtils;
import org.openhab.binding.jeelink.JeeLinkBindingConfig;
import org.openhab.binding.jeelink.JeeLinkBindingProvider;
import org.openhab.core.binding.AbstractActiveBinding;
import org.openhab.core.items.ItemRegistry;
import org.openhab.core.library.types.DecimalType;
import org.openhab.core.types.Command;
import org.openhab.core.types.State;
import org.openhab.io.transport.cul.CULDeviceException;
import org.openhab.io.transport.cul.CULHandler;
import org.openhab.io.transport.cul.CULListener;
import org.openhab.io.transport.cul.CULManager;
import org.openhab.io.transport.cul.CULMode;
import org.osgi.service.cm.ConfigurationException;
import org.osgi.service.cm.ManagedService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * This class implements the communcation between openHAB and JeeLink devices.
 * Via RF received updates are received directly, there is no polling.
 * 
 * @author Till Klocke
 * @since 1.4.0
 */
public class JeeLinkBinding extends AbstractActiveBinding<JeeLinkBindingProvider>
        implements ManagedService, CULListener {

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

    private final static String KEY_DEVICE_NAME = "device";
    @SuppressWarnings("unused")
    private ItemRegistry itemRegistry;

    public void setItemRegistry(ItemRegistry itemRegistry) {
        this.itemRegistry = itemRegistry;
    }

    public void unsetItemRegistry(ItemRegistry itemRegistry) {
        this.itemRegistry = null;
    }

    private String deviceName;

    private CULHandler cul;

    /**
     * the refresh interval which is used to poll values from the JeeLink server
     * (optional, defaults to 60000ms)
     */
    private long refreshInterval = 60000;

    public JeeLinkBinding() {
    }

    public void activate() {
        logger.debug("Activating JeeLink binding");
    }

    private void setNewDeviceName(String deviceName) {
        if (cul != null) {
            CULManager.close(cul);
        }
        this.deviceName = deviceName;
        getCULHandler();
    }

    private void getCULHandler() {
        try {
            logger.debug("Opening CUL device on " + deviceName);
            Map<String, String> options = new HashMap<String, String>();
            options.put("baudrate", "57600");
            options.put("parity", "0"); //parity none
            cul = CULManager.getOpenCULHandler(deviceName, CULMode.SLOW_RF, options);
            cul.registerListener(this);
        } catch (CULDeviceException e) {
            logger.error("Can't open cul device", e);
            cul = null;
        }
    }

    public void deactivate() {
        logger.debug("Deactivating JeeLink binding");
        cul.unregisterListener(this);
        CULManager.close(cul);
    }

    /**
     * @{inheritDoc
     */
    @Override
    protected long getRefreshInterval() {
        return refreshInterval;
    }

    /**
     * @{inheritDoc
     */
    @Override
    protected String getName() {
        return "JeeLink Refresh Service";
    }

    /**
     * @{inheritDoc
     */
    @Override
    protected void execute() {
        // Nothing to do here
    }

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

    }

    /**
     * @{inheritDoc
     */

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

            // to override the default refresh interval one has to add a
            // parameter to openhab.cfg like
            // <bindingName>:refresh=<intervalInMs>
            String refreshIntervalString = (String) config.get("refresh");
            if (StringUtils.isNotBlank(refreshIntervalString)) {
                refreshInterval = Long.parseLong(refreshIntervalString);
            }
            String deviceName = (String) config.get(KEY_DEVICE_NAME);
            if (StringUtils.isEmpty(deviceName)) {
                logger.error("No device name configured");
                setProperlyConfigured(false);
                throw new ConfigurationException(KEY_DEVICE_NAME, "The device name can't be empty");
            } else {
                setNewDeviceName(deviceName);
            }

            setProperlyConfigured(true);
            // read further config parameters here ...

        }
    }

    public void dataReceived(String data) {
        // It is possible that we see here messages of other protocols
        if (data.startsWith("OK")) {
            logger.debug("Received JeeLink message: " + data);
            handleReceivedMessage(data);
        }

    }

    private void handleReceivedMessage(String message) {
        String parts[] = message.split(" ");
        String id = parts[2];
        int a = new Integer(parts[4]);
        int b = new Integer(parts[5]);
        double temp = (a * 256 + b - 1000) * 0.1;
        temp = Math.round(10.0 * temp) / 10.0;
        int lf = Integer.parseInt(parts[6]) & 0x7f;
        int batteryLow = (Integer.parseInt(parts[6]) & 0x80) >> 7;

        JeeLinkBindingConfig configHum = null;
        for (JeeLinkBindingProvider provider : providers) {
            configHum = provider.getConfigForAddress(id + ";H");
            if (configHum != null) {
                break;
            }
        }

        if (configHum != null && needsUpate(configHum) && configHum.getItem() != null) {
            State state = new DecimalType(lf);
            eventPublisher.postUpdate(configHum.getItem().getName(), state);
            configHum.setTimestamp(System.currentTimeMillis());
        }

        JeeLinkBindingConfig configTemp = null;
        for (JeeLinkBindingProvider provider : providers) {
            configTemp = provider.getConfigForAddress(id + ";T");
            if (configTemp != null) {
                break;
            }
        }
        if (configTemp != null && needsUpate(configTemp) && configTemp.getItem() != null) {
            State state = new DecimalType(temp);
            eventPublisher.postUpdate(configTemp.getItem().getName(), state);
            configTemp.setTimestamp(System.currentTimeMillis());
        }

        JeeLinkBindingConfig configBat = null;
        for (JeeLinkBindingProvider provider : providers) {
            configBat = provider.getConfigForAddress(id + ";B");
            if (configBat != null) {
                break;
            }
        }
        if (configBat != null && needsUpate(configBat) && configBat.getItem() != null) {
            State state = new DecimalType(batteryLow);
            eventPublisher.postUpdate(configBat.getItem().getName(), state);
            configBat.setTimestamp(System.currentTimeMillis());
        }

        if (configTemp == null) {
            logger.info("Received message for unknown device " + id);
        }
    }

    public void error(Exception e) {
        logger.error("Error while communicating with CUL", e);

    }

    private boolean needsUpate(JeeLinkBindingConfig config) {
        return System.currentTimeMillis() > config.getTimestamp() + refreshInterval;
    }
}