]> git.basschouten.com Git - openhab-addons.git/commitdiff
[unifi] Guest wifi vouchers (#14284)
authorMark Herwege <mherwege@users.noreply.github.com>
Sat, 28 Jan 2023 20:30:12 +0000 (21:30 +0100)
committerGitHub <noreply@github.com>
Sat, 28 Jan 2023 20:30:12 +0000 (21:30 +0100)
* guest voucher support

Signed-off-by: Mark Herwege <mark.herwege@telenet.be>
12 files changed:
bundles/org.openhab.binding.unifi/README.md
bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/UniFiBindingConstants.java
bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/UniFiVoucherChannelConfig.java [new file with mode: 0644]
bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/UniFiController.java
bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/cache/UniFiControllerCache.java
bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/cache/UniFiVoucherCache.java [new file with mode: 0644]
bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/dto/UniFiSite.java
bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/dto/UniFiVoucher.java [new file with mode: 0644]
bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/util/UniFiVoucherInstanceCreator.java [new file with mode: 0644]
bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/handler/UniFiSiteThingHandler.java
bundles/org.openhab.binding.unifi/src/main/resources/OH-INF/config/config.xml
bundles/org.openhab.binding.unifi/src/main/resources/OH-INF/thing/thing-types.xml

index 8ac81e41cabad2150d513ded0c41e0c279c183d3..fb812a2e26b84dcaeb055d46fa1513f6f44dba12 100644 (file)
@@ -113,12 +113,26 @@ The following table describes the `poePort` configuration parameters:
 
 The `site` information that is retrieved is available as these channels:
 
-| Channel ID      | Item Type | Description                          | Permissions |
-|-----------------|-----------|--------------------------------------|-------------|
-| totalClients    | Number    | Total number of clients connected    | Read        |
-| wirelessClients | Number    | Number of wireless clients connected | Read        |
-| wiredClients    | Number    | Number of wired clients connected    | Read        |
-| guestClients    | Number    | Number of guest clients connected    | Read        |
+| Channel ID            | Item Type | Description                                                            | Permissions |
+|-----------------------|-----------|------------------------------------------------------------------------|-------------|
+| totalClients          | Number    | Total number of clients connected                                      | Read        |
+| wirelessClients       | Number    | Number of wireless clients connected                                   | Read        |
+| wiredClients          | Number    | Number of wired clients connected                                      | Read        |
+| guestClients          | Number    | Number of guest clients connected                                      | Read        |
+| guestVoucher          | String    | Guest voucher for access through the guest portal                      | Read        |
+| guestVouchersGenerate | String    | Generate additional guest vouchers for access through the guest portal | Write       |
+
+The `guestVouchersGenerate` string channel is a command only channel that will trigger voucher creation.
+It has configuration parameters to tailor the vouchers created:
+
+| Parameter                | Description                                                                 | Config   | Default |
+| ------------------------ | --------------------------------------------------------------------------- |--------- | ------- |
+| voucherCount             | Number of vouchers to create                                                | Optional |    1    |
+| voucherExpiration        | Minutes a voucher is valid after activation (default is 1 day)              | Optional |  1440   |
+| voucherUsers             | Number of users for voucher, 0 for no limit                                 | Optional |    1    |
+| voucherUpLimit           | Upload speed limit in kbps, no limit if not set                             | Optional |         |
+| voucherDownLimit         | Download speed limit in kbps, no limit if not set                           | Optional |         |
+| voucherDataQuota         | Data transfer quota in MB per user, no limit if not set                     | Optional |         |
 
 ### `wlan`
 
index 23c70748da76278be18489c90c5ffb9a2dcca3be..7d36ef133c0536f593c858ddf4e406d04b35fa6e 100644 (file)
@@ -24,6 +24,7 @@ import org.openhab.core.thing.ThingTypeUID;
  * @author Matthew Bowman - Initial contribution
  * @author Patrik Wimnell - Blocking / Unblocking client support
  * @author Hilbrand Bouwkamp - Added poePort
+ * @author Mark Herwege - Added guest vouchers
  */
 @NonNullByDefault
 public final class UniFiBindingConstants {
@@ -47,6 +48,8 @@ public final class UniFiBindingConstants {
     public static final String CHANNEL_WIRELESS_CLIENTS = "wirelessClients";
     public static final String CHANNEL_WIRED_CLIENTS = "wiredClients";
     public static final String CHANNEL_GUEST_CLIENTS = "guestClients";
+    public static final String CHANNEL_GUEST_VOUCHER = "guestVoucher";
+    public static final String CHANNEL_GUEST_VOUCHERS_GENERATE = "guestVouchersGenerate";
 
     // List of wlan channels
     public static final String CHANNEL_SECURITY = "security";
@@ -98,6 +101,12 @@ public final class UniFiBindingConstants {
     public static final String PARAMETER_CID = "cid";
     public static final String PARAMETER_SID = "sid";
     public static final String PARAMETER_WID = "wid";
+    public static final String PARAMETER_VOUCHER_COUNT = "voucherCount";
+    public static final String PARAMETER_VOUCHER_EXPIRATION = "voucherExpiration";
+    public static final String PARAMETER_VOUCHER_USERS = "voucherUsers";
+    public static final String PARAMETER_VOUCHER_UP_LIMIT = "voucherUpLimit";
+    public static final String PARAMETER_VOUCHER_DOWN_LIMIT = "voucherDownLimit";
+    public static final String PARAMETER_VOUCHER_DATA_QUOTA = "voucherDataQuota";
     public static final String PARAMETER_PORT_NUMBER = "portNumber";
     public static final String PARAMETER_MAC_ADDRESS = "macAddress";
     public static final String PARAMETER_WIFI_NAME = "wifi";
diff --git a/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/UniFiVoucherChannelConfig.java b/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/UniFiVoucherChannelConfig.java
new file mode 100644 (file)
index 0000000..5f8cc7a
--- /dev/null
@@ -0,0 +1,57 @@
+/**
+ * Copyright (c) 2010-2023 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;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+
+/**
+ * The {@link UniFiVoucherChannelConfig} encapsulates all the configuration options for the guestVouchersGenerate
+ * channel on the UniFi Site thing.
+ *
+ * @author Mark Herwege - Initial contribution
+ */
+@NonNullByDefault
+public class UniFiVoucherChannelConfig {
+
+    private int voucherCount;
+    private int voucherExpiration;
+    private int voucherUsers;
+    private @Nullable Integer voucherUpLimit;
+    private @Nullable Integer voucherDownLimit;
+    private @Nullable Integer voucherDataQuota;
+
+    public int getCount() {
+        return voucherCount;
+    }
+
+    public int getExpiration() {
+        return voucherExpiration;
+    }
+
+    public int getVoucherUsers() {
+        return voucherUsers;
+    }
+
+    public @Nullable Integer getUpLimit() {
+        return voucherUpLimit;
+    }
+
+    public @Nullable Integer getDownLimit() {
+        return voucherDownLimit;
+    }
+
+    public @Nullable Integer getDataQuota() {
+        return voucherDataQuota;
+    }
+}
index 09f36348976cdb225bfa3d560945ead098cb1d7a..18467f9e6ed2f361eeaf63600f592a2cd0320870 100644 (file)
@@ -26,6 +26,7 @@ import org.openhab.binding.unifi.internal.api.dto.UniFiDevice;
 import org.openhab.binding.unifi.internal.api.dto.UniFiSite;
 import org.openhab.binding.unifi.internal.api.dto.UniFiSwitchPorts;
 import org.openhab.binding.unifi.internal.api.dto.UniFiUnknownClient;
+import org.openhab.binding.unifi.internal.api.dto.UniFiVoucher;
 import org.openhab.binding.unifi.internal.api.dto.UniFiWiredClient;
 import org.openhab.binding.unifi.internal.api.dto.UniFiWirelessClient;
 import org.openhab.binding.unifi.internal.api.dto.UniFiWlan;
@@ -34,6 +35,7 @@ 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.openhab.binding.unifi.internal.api.util.UniFiVoucherInstanceCreator;
 import org.openhab.binding.unifi.internal.api.util.UniFiWlanInstanceCreator;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -51,6 +53,7 @@ import com.google.gson.JsonObject;
  * @author Patrik Wimnell - Blocking / Unblocking client support
  * @author Jacob Laursen - Fix online/blocked channels (broken by UniFi Controller 5.12.35)
  * @author Hilbrand Bouwkamp - Added POEPort support, moved generic cache related code to cache object
+ * @author Mark Herwege - Added guest vouchers
  */
 @NonNullByDefault
 public class UniFiController {
@@ -85,6 +88,7 @@ public class UniFiController {
         final UniFiWlanInstanceCreator wlanInstanceCreator = new UniFiWlanInstanceCreator(cache);
         final UniFiDeviceInstanceCreator deviceInstanceCreator = new UniFiDeviceInstanceCreator(cache);
         final UniFiClientInstanceCreator clientInstanceCreator = new UniFiClientInstanceCreator(cache);
+        final UniFiVoucherInstanceCreator voucherInstanceCreator = new UniFiVoucherInstanceCreator(cache);
         this.gson = new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)
                 .registerTypeAdapter(UniFiSite.class, siteInstanceCreator)
                 .registerTypeAdapter(UniFiWlan.class, wlanInstanceCreator)
@@ -92,7 +96,8 @@ public class UniFiController {
                 .registerTypeAdapter(UniFiClient.class, new UniFiClientDeserializer())
                 .registerTypeAdapter(UniFiUnknownClient.class, clientInstanceCreator)
                 .registerTypeAdapter(UniFiWiredClient.class, clientInstanceCreator)
-                .registerTypeAdapter(UniFiWirelessClient.class, clientInstanceCreator).create();
+                .registerTypeAdapter(UniFiWirelessClient.class, clientInstanceCreator)
+                .registerTypeAdapter(UniFiVoucher.class, voucherInstanceCreator).create();
         this.poeGson = new GsonBuilder()
                 .registerTypeAdapter(UnfiPortOverrideJsonObject.class, new UnfiPortOverrideJsonElementDeserializer())
                 .create();
@@ -146,6 +151,7 @@ public class UniFiController {
             refreshDevices(sites);
             refreshClients(sites);
             refreshInsights(sites);
+            refreshVouchers(sites);
         }
     }
 
@@ -209,6 +215,27 @@ public class UniFiController {
         refresh();
     }
 
+    public void generateGuestVouchers(final UniFiSite site, final int count, final int expiration, final int users,
+            @Nullable Integer upLimit, @Nullable Integer downLimit, @Nullable Integer dataQuota) throws UniFiException {
+        final UniFiControllerRequest<Void> req = newRequest(Void.class, HttpMethod.POST, gson);
+        req.setAPIPath(String.format("/api/s/%s/cmd/hotspot", site.getName()));
+        req.setBodyParameter("cmd", "create-voucher");
+        req.setBodyParameter("expire", expiration);
+        req.setBodyParameter("n", count);
+        req.setBodyParameter("quota", users);
+        if (upLimit != null) {
+            req.setBodyParameter("up", upLimit);
+        }
+        if (downLimit != null) {
+            req.setBodyParameter("down", downLimit);
+        }
+        if (dataQuota != null) {
+            req.setBodyParameter("bytes", dataQuota);
+        }
+        executeRequest(req);
+        refresh();
+    }
+
     // Internal API
 
     private <T> UniFiControllerRequest<T> newRequest(final Class<T> responseType, final HttpMethod method,
@@ -284,6 +311,18 @@ public class UniFiController {
         return executeRequest(req);
     }
 
+    private void refreshVouchers(final Collection<UniFiSite> sites) throws UniFiException {
+        for (final UniFiSite site : sites) {
+            cache.putVouchers(getVouchers(site));
+        }
+    }
+
+    private UniFiVoucher @Nullable [] getVouchers(final UniFiSite site) throws UniFiException {
+        final UniFiControllerRequest<UniFiVoucher[]> req = newRequest(UniFiVoucher[].class, HttpMethod.GET, gson);
+        req.setAPIPath(String.format("/api/s/%s/stat/voucher", site.getName()));
+        return executeRequest(req);
+    }
+
     private void refreshInsights(final Collection<UniFiSite> sites) throws UniFiException {
         for (final UniFiSite site : sites) {
             cache.putInsights(getInsights(site));
index df0299f456a5c993a1bb9d2c160f9333041704ae..a38aeb4d08f10442e7ef5bfb3f5120a6685bc534 100644 (file)
@@ -13,6 +13,7 @@
 package org.openhab.binding.unifi.internal.api.cache;
 
 import java.util.Collection;
+import java.util.Comparator;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
@@ -27,6 +28,7 @@ import org.openhab.binding.unifi.internal.api.dto.UniFiDevice;
 import org.openhab.binding.unifi.internal.api.dto.UniFiPortTuple;
 import org.openhab.binding.unifi.internal.api.dto.UniFiSite;
 import org.openhab.binding.unifi.internal.api.dto.UniFiSwitchPorts;
+import org.openhab.binding.unifi.internal.api.dto.UniFiVoucher;
 import org.openhab.binding.unifi.internal.api.dto.UniFiWlan;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -36,6 +38,7 @@ import org.slf4j.LoggerFactory;
  *
  * @author Matthew Bowman - Initial contribution
  * @author Hilbrand Bouwkamp - Moved cache to this dedicated class.
+ * @author Mark Herwege - Added guest vouchers
  */
 @NonNullByDefault
 public class UniFiControllerCache {
@@ -47,6 +50,7 @@ public class UniFiControllerCache {
     private final UniFiDeviceCache devicesCache = new UniFiDeviceCache();
     private final UniFiClientCache clientsCache = new UniFiClientCache();
     private final UniFiClientCache insightsCache = new UniFiClientCache();
+    private final UniFiVoucherCache vouchersCache = new UniFiVoucherCache();
     private final Map<String, UniFiSwitchPorts> devicesToPortTables = new ConcurrentHashMap<>();
 
     public void clear() {
@@ -55,6 +59,7 @@ public class UniFiControllerCache {
         devicesCache.clear();
         clientsCache.clear();
         insightsCache.clear();
+        vouchersCache.clear();
     }
 
     // Sites Cache
@@ -170,4 +175,19 @@ public class UniFiControllerCache {
     public void putInsights(final UniFiClient @Nullable [] insights) {
         insightsCache.putAll(insights);
     }
+
+    // Vouchers Cache
+
+    public void putVouchers(final UniFiVoucher @Nullable [] vouchers) {
+        vouchersCache.putAll(vouchers);
+    }
+
+    public synchronized Stream<UniFiVoucher> getVoucherStreamForSite(final UniFiSite site) {
+        return vouchersCache.values().stream().filter(voucher -> voucher.getSite().equals(site));
+    }
+
+    public @Nullable UniFiVoucher getVoucher(final UniFiSite site) {
+        // Use one of the oldest vouchers first
+        return getVoucherStreamForSite(site).min(Comparator.comparing(UniFiVoucher::getCreateTime)).orElse(null);
+    }
 }
diff --git a/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/cache/UniFiVoucherCache.java b/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/cache/UniFiVoucherCache.java
new file mode 100644 (file)
index 0000000..911f438
--- /dev/null
@@ -0,0 +1,45 @@
+/**
+ * Copyright (c) 2010-2023 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.cache;
+
+import static org.openhab.binding.unifi.internal.api.cache.UniFiCache.Prefix.ID;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+import org.openhab.binding.unifi.internal.api.dto.UniFiVoucher;
+
+/**
+ * The {@link UniFiVoucherCache} is a specific implementation of {@link UniFiCache} for the purpose of caching
+ * {@link UniFiVoucher} instances.
+ *
+ * The cache uses the following prefixes: <code>id</code>
+ *
+ * @author Mark Herwege - Initial contribution
+ */
+@NonNullByDefault
+class UniFiVoucherCache extends UniFiCache<UniFiVoucher> {
+
+    public UniFiVoucherCache() {
+        super(ID);
+    }
+
+    @Override
+    protected @Nullable String getSuffix(final UniFiVoucher voucher, final Prefix prefix) {
+        switch (prefix) {
+            case ID:
+                return voucher.getId();
+            default:
+                return null;
+        }
+    }
+}
index 9eb04a656eb1b3345b01c079551382c9a257650b..9fc925195e23729ace71ff448465240652738c7d 100644 (file)
@@ -20,6 +20,7 @@ import com.google.gson.annotations.SerializedName;
  * The {@link UniFiSite} represents the data model of a UniFi site.
  *
  * @author Matthew Bowman - Initial contribution
+ * @author Mark Herwege - Added guest vouchers
  */
 public class UniFiSite implements HasId {
 
@@ -53,6 +54,14 @@ public class UniFiSite implements HasId {
         return cache;
     }
 
+    public String getVoucher() {
+        UniFiVoucher voucher = cache.getVoucher(this);
+        if (voucher == null) {
+            return null;
+        }
+        return voucher.getCode();
+    }
+
     public boolean isSite(final UniFiSite site) {
         return site != null && id.equals(site.getId());
     }
diff --git a/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/dto/UniFiVoucher.java b/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/dto/UniFiVoucher.java
new file mode 100644 (file)
index 0000000..5a62f6e
--- /dev/null
@@ -0,0 +1,98 @@
+/**
+ * Copyright (c) 2010-2023 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.dto;
+
+import java.time.Instant;
+
+import org.openhab.binding.unifi.internal.api.cache.UniFiControllerCache;
+import org.openhab.binding.unifi.internal.api.util.UniFiTimestampDeserializer;
+
+import com.google.gson.annotations.JsonAdapter;
+import com.google.gson.annotations.SerializedName;
+
+/**
+ * The {@link UniFiVoucher} is the base data model for a guest network voucher
+ *
+ * @author Mark Herwege - Initial contribution
+ */
+public class UniFiVoucher implements HasId {
+
+    private final transient UniFiControllerCache cache;
+
+    @SerializedName("_id")
+    private String id;
+
+    private String siteId;
+
+    private String code;
+    @JsonAdapter(UniFiTimestampDeserializer.class)
+    private Instant createTime;
+    private Integer duration;
+    private Integer quota;
+    private Integer used;
+    private boolean qosOverwrite;
+    private Integer qosUsageQuota;
+    private String status;
+
+    public UniFiVoucher(final UniFiControllerCache cache) {
+        this.cache = cache;
+    }
+
+    @Override
+    public String getId() {
+        return id;
+    }
+
+    public String getCode() {
+        return code;
+    }
+
+    public Instant getCreateTime() {
+        return createTime;
+    }
+
+    public Integer getDuration() {
+        return duration;
+    }
+
+    public Integer getQuota() {
+        return quota;
+    }
+
+    public Integer getUsed() {
+        return used;
+    }
+
+    public boolean isQosOverwrite() {
+        return qosOverwrite;
+    }
+
+    public Integer getQosUsageQuota() {
+        return qosUsageQuota;
+    }
+
+    public String getStatus() {
+        return status;
+    }
+
+    public UniFiSite getSite() {
+        return cache.getSite(siteId);
+    }
+
+    @Override
+    public String toString() {
+        return String.format(
+                "UniFiVoucher{id: '%s', code: '%s', created: '%s', duration: '%s', quota: '%s', used: '%s', qosUsageQuota: '%s', status: '%s', site: %s}",
+                id, code, createTime, duration, quota, used, qosUsageQuota, status, getSite());
+    }
+}
diff --git a/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/util/UniFiVoucherInstanceCreator.java b/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/util/UniFiVoucherInstanceCreator.java
new file mode 100644 (file)
index 0000000..d63c80e
--- /dev/null
@@ -0,0 +1,48 @@
+/**
+ * Copyright (c) 2010-2023 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.util;
+
+import java.lang.reflect.Type;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+import org.openhab.binding.unifi.internal.api.cache.UniFiControllerCache;
+import org.openhab.binding.unifi.internal.api.dto.UniFiVoucher;
+
+import com.google.gson.InstanceCreator;
+import com.google.gson.JsonSyntaxException;
+
+/**
+ * The {@link UniFiVoucherInstanceCreator} creates instances of {@link UniFiVoucher}s during the JSON unmarshalling of
+ * controller responses.
+ *
+ * @author Mark Herwege - Initial contribution
+ */
+@NonNullByDefault
+public class UniFiVoucherInstanceCreator implements InstanceCreator<UniFiVoucher> {
+
+    private final UniFiControllerCache cache;
+
+    public UniFiVoucherInstanceCreator(final UniFiControllerCache cache) {
+        this.cache = cache;
+    }
+
+    @Override
+    public UniFiVoucher createInstance(final @Nullable Type type) {
+        if (UniFiVoucher.class.equals(type)) {
+            return new UniFiVoucher(cache);
+        } else {
+            throw new JsonSyntaxException("Expected a UniFi Voucher type, but got " + type);
+        }
+    }
+}
index 53ebb0969866236fdd49391619ce6e86ce193dfe..2fa53634903a7a8075d1b9cc9b843c9b5c7266bc 100644 (file)
  */
 package org.openhab.binding.unifi.internal.handler;
 
-import static org.openhab.binding.unifi.internal.UniFiBindingConstants.CHANNEL_GUEST_CLIENTS;
-import static org.openhab.binding.unifi.internal.UniFiBindingConstants.CHANNEL_TOTAL_CLIENTS;
-import static org.openhab.binding.unifi.internal.UniFiBindingConstants.CHANNEL_WIRED_CLIENTS;
-import static org.openhab.binding.unifi.internal.UniFiBindingConstants.CHANNEL_WIRELESS_CLIENTS;
+import static org.openhab.binding.unifi.internal.UniFiBindingConstants.*;
+
+import java.util.function.Predicate;
 
 import org.eclipse.jdt.annotation.NonNullByDefault;
 import org.eclipse.jdt.annotation.Nullable;
 import org.openhab.binding.unifi.internal.UniFiSiteThingConfig;
+import org.openhab.binding.unifi.internal.UniFiVoucherChannelConfig;
 import org.openhab.binding.unifi.internal.api.UniFiController;
 import org.openhab.binding.unifi.internal.api.UniFiException;
 import org.openhab.binding.unifi.internal.api.cache.UniFiControllerCache;
+import org.openhab.binding.unifi.internal.api.dto.UniFiClient;
 import org.openhab.binding.unifi.internal.api.dto.UniFiSite;
 import org.openhab.core.library.types.DecimalType;
+import org.openhab.core.library.types.OnOffType;
+import org.openhab.core.library.types.StringType;
+import org.openhab.core.thing.Channel;
 import org.openhab.core.thing.ChannelUID;
 import org.openhab.core.thing.Thing;
 import org.openhab.core.thing.ThingStatus;
@@ -39,6 +43,7 @@ import org.openhab.core.types.UnDefType;
  *
  * @author Matthew Bowman - Initial contribution
  * @author Hilbrand Bouwkamp - Initial contribution
+ * @author Mark Herwege - Added guest vouchers
  */
 @NonNullByDefault
 public class UniFiSiteThingHandler extends UniFiBaseThingHandler<UniFiSite, UniFiSiteThingConfig> {
@@ -67,32 +72,59 @@ public class UniFiSiteThingHandler extends UniFiBaseThingHandler<UniFiSite, UniF
 
     @Override
     protected State getChannelState(final UniFiSite site, final String channelId) {
-        final UniFiControllerCache cache = site.getCache();
-        final long count;
+        final State state;
 
         switch (channelId) {
             case CHANNEL_TOTAL_CLIENTS:
-                count = cache.countClients(site, c -> true);
+                state = countClients(site, c -> true);
                 break;
             case CHANNEL_WIRELESS_CLIENTS:
-                count = cache.countClients(site, c -> c.isWireless());
+                state = countClients(site, c -> c.isWireless());
                 break;
             case CHANNEL_WIRED_CLIENTS:
-                count = cache.countClients(site, c -> c.isWired());
+                state = countClients(site, c -> c.isWired());
                 break;
             case CHANNEL_GUEST_CLIENTS:
-                count = cache.countClients(site, c -> c.isGuest());
+                state = countClients(site, c -> c.isGuest());
+                break;
+            case CHANNEL_GUEST_VOUCHER:
+                String voucher = site.getVoucher();
+                state = (voucher != null) ? StringType.valueOf(voucher) : UnDefType.UNDEF;
+                break;
+            case CHANNEL_GUEST_VOUCHERS_GENERATE:
+                state = OnOffType.OFF;
                 break;
             default:
                 // Unsupported channel; nothing to update
                 return UnDefType.NULL;
         }
-        return new DecimalType(count);
+        return state;
+    }
+
+    private static State countClients(final UniFiSite site, final Predicate<UniFiClient> filter) {
+        return new DecimalType(site.getCache().countClients(site, filter));
     }
 
     @Override
     protected boolean handleCommand(final UniFiController controller, final UniFiSite entity,
             final ChannelUID channelUID, final Command command) throws UniFiException {
+        final String channelID = channelUID.getId();
+
+        if (CHANNEL_GUEST_VOUCHERS_GENERATE.equals(channelID)) {
+            Channel channel = getThing().getChannel(CHANNEL_GUEST_VOUCHERS_GENERATE);
+            if (channel == null) {
+                return false;
+            }
+            UniFiVoucherChannelConfig config = channel.getConfiguration().as(UniFiVoucherChannelConfig.class);
+            final int count = config.getCount();
+            final int expire = config.getExpiration();
+            final int users = config.getVoucherUsers();
+            final Integer upLimit = config.getUpLimit();
+            final Integer downLimit = config.getDownLimit();
+            final Integer dataQuota = config.getDataQuota();
+            controller.generateGuestVouchers(entity, count, expire, users, upLimit, downLimit, dataQuota);
+            return true;
+        }
         return false;
     }
 }
index 1d5cc7881ae2b4b54fe5c531a92d720ebe74d94e..fdd76010d2c127f42faf5deecf2a08d70cb9554f 100644 (file)
                </parameter>
        </config-description>
 
+       <config-description uri="channel-type:unifi:guestVouchersGenerate">
+               <parameter name="voucherCount" type="integer">
+                       <label>Number</label>
+                       <description>Number of vouchers to create</description>
+                       <default>1</default>
+               </parameter>
+               <parameter name="voucherExpiration" type="integer" unit="min">
+                       <label>Expiration Time</label>
+                       <description>Minutes a voucher is valid after activation</description>
+                       <default>1440</default>
+               </parameter>
+               <parameter name="voucherUsers" type="integer">
+                       <label>Users</label>
+                       <description>Number of users for voucher, 0 if no limit</description>
+                       <default>1</default>
+               </parameter>
+               <parameter name="voucherUpLimit" type="integer">
+                       <label>Upload Speed Limit</label>
+                       <description>Upload speed limit in kbps, no limit if not set</description>
+               </parameter>
+               <parameter name="voucherDownLimit" type="integer">
+                       <label>Download Speed Limit</label>
+                       <description>Download speed limit in kbps, no limit if not set</description>
+               </parameter>
+               <parameter name="voucherDataQuota" type="integer">
+                       <label>Data Transfer Quota</label>
+                       <description>Data transfer quota in MB per user, no limit if not set</description>
+               </parameter>
+       </config-description>
+
        <config-description uri="thing-type:unifi:poePort">
                <parameter name="portNumber" type="integer" required="true">
                        <label>Port Number</label>
index 132992cd5babe2d036efe4fa4b5816089c83bd3e..640a10e51109baa895eb700267153cf4b959be52 100644 (file)
@@ -25,6 +25,8 @@
                        <channel id="wirelessClients" typeId="wirelessClients"/>
                        <channel id="wiredClients" typeId="wiredClients"/>
                        <channel id="guestClients" typeId="guestClients"/>
+                       <channel id="guestVoucher" typeId="guestVoucher"/>
+                       <channel id="guestVouchersGenerate" typeId="guestVouchersGenerate"/>
                </channels>
 
                <representation-property>sid</representation-property>
                <state readOnly="true"></state>
        </channel-type>
 
+       <channel-type id="guestVoucher">
+               <item-type>String</item-type>
+               <label>Guest Voucher</label>
+               <description>Guest voucher for access through the guest portal</description>
+               <state readOnly="true"></state>
+       </channel-type>
+
+       <channel-type id="guestVouchersGenerate">
+               <item-type>String</item-type>
+               <label>Generate Guest Vouchers</label>
+               <description>Generate additional guest vouchers for access through the guest portal</description>
+               <command>
+                       <options>
+                               <option value="GENERATE">Generate</option>
+                       </options>
+               </command>
+               <config-description-ref uri="channel-type:unifi:guestVouchersGenerate"/>
+       </channel-type>
+
        <channel-type id="wlanEnable">
                <item-type>Switch</item-type>
                <label>Enable</label>