org.openhab.binding.unifi.internal.api.model.UniFiController.java Source code

Java tutorial

Introduction

Here is the source code for org.openhab.binding.unifi.internal.api.model.UniFiController.java

Source

/**
 * Copyright (c) 2010-2019 Contributors to the openHAB project
 *
 * See the NOTICE file(s) distributed with this work for additional
 * information.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0
 *
 * SPDX-License-Identifier: EPL-2.0
 */
package org.openhab.binding.unifi.internal.api.model;

import java.util.Collection;

import org.apache.commons.lang.StringUtils;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.jetty.client.HttpClient;
import org.openhab.binding.unifi.internal.api.UniFiException;
import org.openhab.binding.unifi.internal.api.UniFiExpiredSessionException;
import org.openhab.binding.unifi.internal.api.UniFiNotAuthorizedException;
import org.openhab.binding.unifi.internal.api.cache.UniFiClientCache;
import org.openhab.binding.unifi.internal.api.cache.UniFiDeviceCache;
import org.openhab.binding.unifi.internal.api.cache.UniFiSiteCache;
import org.openhab.binding.unifi.internal.api.util.UniFiClientDeserializer;
import org.openhab.binding.unifi.internal.api.util.UniFiClientInstanceCreator;
import org.openhab.binding.unifi.internal.api.util.UniFiDeviceInstanceCreator;
import org.openhab.binding.unifi.internal.api.util.UniFiSiteInstanceCreator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.gson.FieldNamingPolicy;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

/**
 * The {@link UniFiController} is the main communication point with an external instance of the Ubiquiti Networks
 * Controller Software.
 *
 * @author Matthew Bowman - Initial contribution
 * @author Patrik Wimnell - Blocking / Unblocking client support
 */
@NonNullByDefault
public class UniFiController {

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

    private UniFiSiteCache sitesCache = new UniFiSiteCache();

    private UniFiDeviceCache devicesCache = new UniFiDeviceCache();

    private UniFiClientCache clientsCache = new UniFiClientCache();

    private UniFiClientCache insightsCache = new UniFiClientCache();

    private final HttpClient httpClient;

    private final String host;

    private final int port;

    private final String username;

    private final String password;

    private final Gson gson;

    public UniFiController(HttpClient httpClient, String host, int port, String username, String password) {
        this.httpClient = httpClient;
        this.host = host;
        this.port = port;
        this.username = username;
        this.password = password;
        UniFiSiteInstanceCreator siteInstanceCreator = new UniFiSiteInstanceCreator(this);
        UniFiDeviceInstanceCreator deviceInstanceCreator = new UniFiDeviceInstanceCreator(this);
        UniFiClientInstanceCreator clientInstanceCreator = new UniFiClientInstanceCreator(this);
        this.gson = new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)
                .registerTypeAdapter(UniFiSite.class, siteInstanceCreator)
                .registerTypeAdapter(UniFiDevice.class, deviceInstanceCreator)
                .registerTypeAdapter(UniFiClient.class, new UniFiClientDeserializer())
                .registerTypeAdapter(UniFiUnknownClient.class, clientInstanceCreator)
                .registerTypeAdapter(UniFiWiredClient.class, clientInstanceCreator)
                .registerTypeAdapter(UniFiWirelessClient.class, clientInstanceCreator).create();
    }

    // Public API

    public void start() throws UniFiException {
        login();
    }

    public void stop() throws UniFiException {
        logout();
    }

    public void login() throws UniFiException {
        UniFiControllerRequest<Void> req = newRequest(Void.class);
        req.setPath("/api/login");
        req.setBodyParameter("username", username);
        req.setBodyParameter("password", password);
        // scurb: Changed strict = false to make blocking feature work
        req.setBodyParameter("strict", false);
        req.setBodyParameter("remember", false);
        executeRequest(req);
    }

    public void logout() throws UniFiException {
        UniFiControllerRequest<Void> req = newRequest(Void.class);
        req.setPath("/logout");
        executeRequest(req);
    }

    public void refresh() throws UniFiException {
        synchronized (this) {
            sitesCache = getSites();
            devicesCache = getDevices();
            clientsCache = getClients();
            insightsCache = getInsights();
        }
    }

    // Site API

    public @Nullable UniFiSite getSite(@Nullable String id) {
        UniFiSite site = null;
        if (StringUtils.isNotBlank(id)) {
            synchronized (this) {
                site = sitesCache.get(id);
            }
            if (site == null) {
                logger.debug("Could not find a matching site for id = '{}'", id);
            }
        }
        return site;
    }

    // Device API

    public @Nullable UniFiDevice getDevice(@Nullable String id) {
        UniFiDevice device = null;
        if (StringUtils.isNotBlank(id)) {
            synchronized (this) {
                device = devicesCache.get(id);
            }
            if (device == null) {
                logger.debug("Could not find a matching device for id = '{}'", id);
            }
        }
        return device;
    }

    // Client API

    public @Nullable UniFiClient getClient(@Nullable String id) {
        UniFiClient client = null;
        if (StringUtils.isNotBlank(id)) {
            synchronized (this) {
                // mgb: first check active clients and fallback to insights if not found
                client = clientsCache.get(id);
                if (client == null) {
                    client = insightsCache.get(id);
                }
            }
            if (client == null) {
                logger.debug("Could not find a matching client for id = {}", id);
            }
        }
        return client;
    }

    protected void block(UniFiClient client, boolean blocked) throws UniFiException {
        UniFiControllerRequest<Void> req = newRequest(Void.class);
        req.setPath("/api/s/" + client.getSite().getName() + "/cmd/stamgr");
        req.setBodyParameter("cmd", blocked ? "block-sta" : "unblock-sta");
        req.setBodyParameter("mac", client.getMac());
        executeRequest(req);
    }

    protected void reconnect(UniFiClient client) throws UniFiException {
        UniFiControllerRequest<Void> req = newRequest(Void.class);
        req.setPath("/api/s/" + client.getSite().getName() + "/cmd/stamgr");
        req.setBodyParameter("cmd", "kick-sta");
        req.setBodyParameter("mac", client.getMac());
        executeRequest(req);
    }

    // Internal API

    private <T> UniFiControllerRequest<T> newRequest(Class<T> responseType) {
        return new UniFiControllerRequest<T>(responseType, gson, httpClient, host, port);
    }

    private <T> @Nullable T executeRequest(UniFiControllerRequest<T> request) throws UniFiException {
        T result;
        try {
            result = request.execute();
        } catch (UniFiExpiredSessionException e) {
            login();
            result = executeRequest(request);
        } catch (UniFiNotAuthorizedException e) {
            logger.warn("Not Authorized! Please make sure your controller credentials have administrator rights");
            result = null;
        }
        return result;
    }

    private UniFiSiteCache getSites() throws UniFiException {
        UniFiControllerRequest<UniFiSite[]> req = newRequest(UniFiSite[].class);
        req.setPath("/api/self/sites");
        UniFiSite[] sites = executeRequest(req);
        UniFiSiteCache cache = new UniFiSiteCache();
        if (sites != null) {
            logger.debug("Found {} UniFi Site(s): {}", sites.length, lazyFormatAsList(sites));
            for (UniFiSite site : sites) {
                cache.put(site);
            }
        }
        return cache;
    }

    private UniFiDeviceCache getDevices() throws UniFiException {
        UniFiDeviceCache cache = new UniFiDeviceCache();
        Collection<UniFiSite> sites = sitesCache.values();
        for (UniFiSite site : sites) {
            cache.putAll(getDevices(site));
        }
        return cache;
    }

    private UniFiDeviceCache getDevices(UniFiSite site) throws UniFiException {
        UniFiControllerRequest<UniFiDevice[]> req = newRequest(UniFiDevice[].class);
        req.setPath("/api/s/" + site.getName() + "/stat/device");
        UniFiDevice[] devices = executeRequest(req);
        UniFiDeviceCache cache = new UniFiDeviceCache();
        if (devices != null) {
            logger.debug("Found {} UniFi Device(s): {}", devices.length, lazyFormatAsList(devices));
            for (UniFiDevice device : devices) {
                cache.put(device);
            }
        }
        return cache;
    }

    private UniFiClientCache getClients() throws UniFiException {
        UniFiClientCache cache = new UniFiClientCache();
        Collection<UniFiSite> sites = sitesCache.values();
        for (UniFiSite site : sites) {
            cache.putAll(getClients(site));
        }
        return cache;
    }

    private UniFiClientCache getClients(UniFiSite site) throws UniFiException {
        UniFiControllerRequest<UniFiClient[]> req = newRequest(UniFiClient[].class);
        req.setPath("/api/s/" + site.getName() + "/stat/sta");
        UniFiClient[] clients = executeRequest(req);
        UniFiClientCache cache = new UniFiClientCache();
        if (clients != null) {
            logger.debug("Found {} UniFi Client(s): {}", clients.length, lazyFormatAsList(clients));
            for (UniFiClient client : clients) {
                cache.put(client);
            }
        }
        return cache;
    }

    private UniFiClientCache getInsights() throws UniFiException {
        UniFiClientCache cache = new UniFiClientCache();
        Collection<UniFiSite> sites = sitesCache.values();
        for (UniFiSite site : sites) {
            cache.putAll(getInsights(site));
        }
        return cache;
    }

    private UniFiClientCache getInsights(UniFiSite site) throws UniFiException {
        UniFiControllerRequest<UniFiClient[]> req = newRequest(UniFiClient[].class);
        req.setPath("/api/s/" + site.getName() + "/stat/alluser");
        req.setQueryParameter("within", 168); // scurb: Changed to 7 days.
        UniFiClient[] clients = executeRequest(req);
        UniFiClientCache cache = new UniFiClientCache();
        if (clients != null) {
            logger.debug("Found {} UniFi Insights(s): {}", clients.length, lazyFormatAsList(clients));
            for (UniFiClient client : clients) {
                cache.put(client);
            }
        }
        return cache;
    }

    private static Object lazyFormatAsList(Object[] arr) {
        return new Object() {

            @Override
            public String toString() {
                String value = "";
                for (Object o : arr) {
                    value += "\n - " + o.toString();
                }
                return value;
            }

        };
    }

}