org.openhab.binding.fritzboxtr064.internal.FritzboxTr064Binding.java Source code

Java tutorial

Introduction

Here is the source code for org.openhab.binding.fritzboxtr064.internal.FritzboxTr064Binding.java

Source

/**
 * Copyright (c) 2010-2019 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.binding.fritzboxtr064.internal;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;

import org.apache.commons.lang.StringUtils;
import org.openhab.binding.fritzboxtr064.FritzboxTr064BindingProvider;
import org.openhab.binding.fritzboxtr064.internal.FritzboxTr064GenericBindingProvider.FritzboxTr064BindingConfig;
import org.openhab.core.binding.AbstractActiveBinding;
import org.openhab.core.items.Item;
import org.openhab.core.library.items.ContactItem;
import org.openhab.core.library.items.NumberItem;
import org.openhab.core.library.items.StringItem;
import org.openhab.core.library.items.SwitchItem;
import org.openhab.core.library.types.DecimalType;
import org.openhab.core.library.types.OnOffType;
import org.openhab.core.library.types.OpenClosedType;
import org.openhab.core.library.types.StringType;
import org.openhab.core.types.Command;
import org.openhab.core.types.State;
import org.osgi.framework.BundleContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Implement this class if you are going create an actively polling service
 * like querying a Website/Device.
 *
 * @author gitbock
 * @since 1.8.0
 */
public class FritzboxTr064Binding extends AbstractActiveBinding<FritzboxTr064BindingProvider> {

    private static class ItemDescription {
        private final String _name;

        private final Class<? extends Item> _type;

        public ItemDescription(String _name, Class<? extends Item> _type) {
            this._name = _name;
            this._type = _type;
        }

        public String getName() {
            return _name;
        }

        public Class<? extends Item> getType() {
            return _type;
        }

    }

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

    // URL to connect to fbox. Provided in main cfg file
    private String _url;

    // Username to use to connect to fbox
    private String _user;

    // PW
    private String _pw;

    // Phonebook ID
    private int _pbid;

    // Call monitor class/including thread
    private CallMonitor _callMonitor;

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

    // holds Fbox TR064 connection
    private Tr064Comm _fboxComm = null;

    private PhonebookManager _pbm = null;

    public FritzboxTr064Binding() {
    }

    /**
     * Called by the SCR to activate the component with its configuration read from CAS
     *
     * @param bundleContext BundleContext of the Bundle that defines this component
     * @param configuration Configuration properties for this component obtained from the ConfigAdmin service
     */
    public void activate(final BundleContext bundleContext, final Map<String, Object> configuration) {
        logger.debug("FritzBox TR064 Binding activated!");

        // to override the default refresh interval one has to add a
        // parameter to openhab.cfg like <bindingName>:refresh=<intervalInMs>
        String refreshIntervalString = Objects.toString(configuration.get("refresh"), null);
        if (StringUtils.isNotBlank(refreshIntervalString)) {
            refreshInterval = Long.parseLong(refreshIntervalString);
            logger.debug("Custom refresh interval set to {}", refreshInterval);
        }

        // Check if fritzbox parameters were provided in config, otherwise does not make sense going on...
        String fboxurl = Objects.toString(configuration.get("url"), null);
        String fboxuser = Objects.toString(configuration.get("user"), null);
        String fboxpw = Objects.toString(configuration.get("pass"), null);
        String fboxphonebookid = Objects.toString(configuration.get("phonebookid"), null);
        if (fboxurl == null) {
            logger.warn("Fritzbox URL was not provided in config. Shutting down binding.");
            // how to shutdown??
            setProperlyConfigured(false);
            return;
        }
        if (fboxuser == null) {
            logger.warn("Fritzbox User was not provided in config. Using default username.");
        }
        if (fboxpw == null) {
            logger.warn("Fritzbox Password was not provided in config. Shutting down binding.");
            // how to shutdown??
            setProperlyConfigured(false);
            return;
        }
        if (fboxphonebookid == null) {
            logger.debug("No Phonebookid provided. Use default: 0");
            fboxphonebookid = "0";
        }
        this._pw = fboxpw;
        this._user = fboxuser;
        this._url = fboxurl;

        try {
            this._pbid = Integer.valueOf(fboxphonebookid);
        } catch (NumberFormatException ex) { // set fallback to 0
            this._pbid = 0;
        }

        if (_fboxComm == null) {
            _fboxComm = new Tr064Comm(_url, _user, _pw);
        }

        setProperlyConfigured(true);

    }

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

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

    /**
     * @{inheritDoc}
     */
    @Override
    protected void execute() {
        logger.trace("FritzboxTr064 executing...");

        Map<ItemConfiguration, ItemDescription> itemsByConfiguration = new HashMap<>();
        List<ItemConfiguration> itemConfigurations = new ArrayList<>();

        for (FritzboxTr064BindingProvider provider : providers) {
            for (String itemName : provider.getItemNames()) { // check each item relevant for this binding
                FritzboxTr064BindingConfig conf = provider.getBindingConfigByItemName(itemName); // extract itemconfig
                                                                                                 // for current item
                if (conf.getConfigString().startsWith("callmonitor")) {
                    // check if we need to start call monitor
                    if (_callMonitor == null) { // not started yet
                        logger.debug(
                                "call monitor is not running. Configured items require call monitor -> Starting call monitor...");

                        if (_pbm == null) {
                            logger.debug("Downloading phonebooks");
                            _pbm = new PhonebookManager(_fboxComm);
                            _pbm.downloadPhonebooks(_pbid);
                        }

                        _callMonitor = new CallMonitor(_url, eventPublisher, providers, _pbm);
                        _callMonitor.setupReconnectJob();
                        _callMonitor.startThread();
                    }
                    continue; // make sure, no callmonitor items are processed by tr064
                }

                ItemConfiguration request = ItemConfiguration.parse(conf.getConfigString());
                itemConfigurations.add(request);
                itemsByConfiguration.put(request, new ItemDescription(itemName, conf.getItemType()));
            }
        }

        Map<ItemConfiguration, String> resultsByConfiguration = _fboxComm.getTr064Values(itemConfigurations);

        for (Entry<ItemConfiguration, ItemDescription> entry : itemsByConfiguration.entrySet()) {
            ItemConfiguration itemConfiguration = entry.getKey();
            ItemDescription item = entry.getValue();
            String itemName = item.getName();
            Class<? extends Item> itemType = item.getType();

            String tr064result = resultsByConfiguration.get(itemConfiguration);

            if (tr064result == null) { // if value cannot be read
                tr064result = "ERR";
            }
            if (itemType.isAssignableFrom(StringItem.class)) {
                eventPublisher.postUpdate(itemName, new StringType(tr064result));
            } else if (itemType.isAssignableFrom(ContactItem.class)) {
                State newState = tr064result.equals("1") ? OpenClosedType.OPEN : OpenClosedType.CLOSED;
                eventPublisher.postUpdate(itemName, newState);
            } else if (itemType.isAssignableFrom(SwitchItem.class)) {
                State newState = tr064result.equals("1") ? OnOffType.ON : OnOffType.OFF;
                eventPublisher.postUpdate(itemName, newState);
            } else if (itemType.isAssignableFrom(NumberItem.class)) { // number items e.g. TAM messages
                // tr064 retrieves only Strings, trying to parse value returned
                long val = 0;
                try {
                    val = Long.parseLong(tr064result);
                } catch (NumberFormatException ex) {
                    val = -1; // indicate error as -1
                }

                State newState = new DecimalType(val);
                eventPublisher.postUpdate(itemName, newState);
            }
        }

    }

    /**
     * @{inheritDoc}
     */
    @Override
    protected void internalReceiveCommand(String itemName, Command command) {
        logger.trace("internalReceiveCommand({},{}) is called!", itemName, command);
        if (_fboxComm == null) {
            _fboxComm = new Tr064Comm(_url, _user, _pw);
        }
        // Search Item Binding config for this itemName
        for (FritzboxTr064BindingProvider provider : providers) {
            FritzboxTr064BindingConfig conf = provider.getBindingConfigByItemName(itemName);
            if (conf != null) {
                ItemConfiguration request = ItemConfiguration.parse(conf.getConfigString()); // pass config String
                                                                                             // because config string
                                                                                             // needed for finding item
                                                                                             // map
                _fboxComm.setTr064Value(request, command);

            }
        }
    }

    protected void addBindingProvider(FritzboxTr064BindingProvider bindingProvider) {
        super.addBindingProvider(bindingProvider);
    }

    protected void removeBindingProvider(FritzboxTr064BindingProvider bindingProvider) {
        super.removeBindingProvider(bindingProvider);
    }

}