[unifi] guest voucher actions ()

* guest voucher actions

Signed-off-by: Mark Herwege <mark.herwege@telenet.be>
This commit is contained in:
Mark Herwege 2023-02-05 16:59:51 +01:00 committed by GitHub
parent bc6a027f9e
commit fbbce11cf2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 440 additions and 29 deletions
bundles/org.openhab.binding.unifi

@ -230,21 +230,89 @@ The `poePort` information that is retrieved is available as these channels:
The `enable` switch channel has a configuration parameter `mode` which is the value used to switch PoE on when the channel is switched to ON.
The default mode value is `auto`.
## Rule Actions
As an alternative to using the `guestVoucher` and `guestVouchersGenerate` channels on the `site` thing, it is possible to use rule actions on the thing to generate, revoke and list guest vouchers.
The following actions are available:
- `boolean success = generateVoucher(Integer expire, Integer users, Integer upLimit, Integer downLimit, Integer dataQuota)`
- `boolean success = generateVouchers(Integer count, Integer expire, Integer users, Integer upLimit, Integer downLimit, Integer dataQuota)`
- `boolean success = revokeVoucher(String voucherCode)`
- `boolean success = revokeVouchers(List<String> voucherCodes)`
- `boolean success = revokeAllVouchers()`
- `String vouchers = listVouchers()`
Since there is a separate rule action instance for each `site` thing, this needs to be retrieved through `getActions(scope, thingUID)`.
The first parameter always has to be `unifi` and the second is the full Thing UID of the site that should be used.
Once this action instance is retrieved, you can invoke the action method on it.
Boolean return values for the actions indicate success or failure.
The `generateVoucher(s)` actions parameters match the configuration parameters for the `guestVouchersGenerate` channel.
With the actions, these parameters can be controlled in a rule or script.
`null` values for the parameters are allowed, and will set the parameter to the default value.
| Parameter | Description | Default |
| ------------- | --------------------------------------------------------------------------- | ------- |
| count | Number of vouchers to create | 1 |
| expire | Minutes a voucher is valid after activation (default is 1 day) | 1440 |
| users | Number of users for voucher, 0 for no limit | 1 |
| upLimit | Upload speed limit in kbps, no limit if not set | |
| downLimit | Download speed limit in kbps, no limit if not set | |
| dataQuota | Data transfer quota in MB per user, no limit if not set | |
The `revoke...` actions allow you to revoke previously created vouchers.
The parameter is the voucher code or a list of voucher codes to be revoked.
The `listVouchers` action will return a json string representing the currently available vouchers for the site.
The json contains all parameters for the voucher, therefore it is possible to filter on these in a rule or script.
For example, one could retrieve all vouchers created before a certain time and use the `revokeVouchers` action to delete these.
The structure of the returned json is (depending on content, some fields may be missing):
```json
[
{
"code": "3867791284",
"createTime": "2023-01-31T14:40:47Z",
"duration": 1440,
"quota": 2,
"used": 0,
"qosUsageQuota": 300,
"qosRateMaxUp": 200,
"qosRateMaxDown": 100,
"qosOverwrite": true,
"note": "I added a note when creating vouchers in the UniFi hotspot UI",
"status": "VALID_MULTI"
},
{
"code": "0021952641",
"createTime": "2023-01-31T14:38:47Z",
"duration": 1440,
"quota": 1,
"used": 0,
"qosOverwrite": false,
"status": "VALID_ONE"
},
{ ... }
]
```
## Full Example
things/unifi.things
### `things/unifi.things`
```
Bridge unifi:controller:home "UniFi Controller" [ host="unifi", port=8443, unifios=false, username="$username", password="$password", refresh=10 ] {
Thing wirelessClient matthewsPhone "Matthew's iPhone" [ cid="$cid", site="default", considerHome=180 ]
Thing site mysite "My Site" [ sid="$sid" ]
}
```
_Note: Usually on Unifi OS, the default port is 443_
Replace `$user`, `$password` and `$cid` accordingly.
Replace `$user`, `$password`, `$cid` and `$sid` accordingly.
items/unifi.items
### `items/unifi.items`
```
Switch MatthewsPhone "Matthew's iPhone [MAP(unifi.map):%s]" { channel="unifi:wirelessClient:home:matthewsPhone:online" }
@ -260,14 +328,14 @@ Switch MatthewsPhoneBlocked "Matthew's iPhone: Blocked"
Switch MatthewsPhoneReconnect "Matthew's iPhone: Reconnect" { channel="unifi:wirelessClient:home:matthewsPhone:reconnect" }
```
transform/unifi.map
### `transform/unifi.map`
```
ON=Home
OFF=Away
```
sitemaps/unifi.sitemap
### `sitemaps/unifi.sitemap`
```
sitemap unifi label="UniFi Binding"
@ -287,3 +355,23 @@ sitemap unifi label="UniFi Binding"
}
}
```
### `rule actions` for `site` thing
```java
val uniFiActions = getActions("unifi","unifi:site:home:mysite")
val success = uniFiActions.generateVoucher(null, null, null, 100, 500, 250)
```
```java
val uniFiActions = getActions("unifi","unifi:site:home:mysite")
val vouchersJson = uniFiActions.listVouchers()
```
```java
import java.util.List
val List<String> voucherList = newArrayList("38677-91284", "46415-36104")
val uniFiActions = getActions("unifi","unifi:site:home:mysite")
val success = uniFiActions.revokeVouchers(voucherList)
```

@ -12,13 +12,7 @@
*/
package org.openhab.binding.unifi.internal;
import static org.openhab.binding.unifi.internal.UniFiBindingConstants.ALL_THING_TYPE_SUPPORTED;
import static org.openhab.binding.unifi.internal.UniFiBindingConstants.THING_TYPE_CONTROLLER;
import static org.openhab.binding.unifi.internal.UniFiBindingConstants.THING_TYPE_POE_PORT;
import static org.openhab.binding.unifi.internal.UniFiBindingConstants.THING_TYPE_SITE;
import static org.openhab.binding.unifi.internal.UniFiBindingConstants.THING_TYPE_WIRED_CLIENT;
import static org.openhab.binding.unifi.internal.UniFiBindingConstants.THING_TYPE_WIRELESS_CLIENT;
import static org.openhab.binding.unifi.internal.UniFiBindingConstants.THING_TYPE_WLAN;
import static org.openhab.binding.unifi.internal.UniFiBindingConstants.*;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;

@ -0,0 +1,271 @@
/**
* 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.action;
import java.util.List;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.unifi.internal.api.UniFiController;
import org.openhab.binding.unifi.internal.api.UniFiException;
import org.openhab.binding.unifi.internal.api.dto.UniFiSite;
import org.openhab.binding.unifi.internal.api.dto.UniFiVoucher;
import org.openhab.binding.unifi.internal.handler.UniFiSiteThingHandler;
import org.openhab.core.automation.annotation.ActionInput;
import org.openhab.core.automation.annotation.ActionOutput;
import org.openhab.core.automation.annotation.RuleAction;
import org.openhab.core.thing.binding.ThingActions;
import org.openhab.core.thing.binding.ThingActionsScope;
import org.openhab.core.thing.binding.ThingHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.gson.Gson;
/**
* The {@link UniFiSiteActions} class defines rule actions for creating guest hotspot vouchers
*
* @author Mark Herwege - Initial contribution
*/
@ThingActionsScope(name = "unifi")
@NonNullByDefault
public class UniFiSiteActions implements ThingActions {
private static final int DEFAULT_COUNT = 1;
private static final int DEFAULT_EXPIRE_MIN = 1440;
private static final int DEFAULT_USERS = 1;
private static final Pattern NON_DIGITS_PATTERN = Pattern.compile("\\D+");
private final Logger logger = LoggerFactory.getLogger(UniFiSiteActions.class);
private @Nullable UniFiSiteThingHandler handler;
private final Gson gson = new Gson();
@RuleAction(label = "@text/action.unifi.generateVouchers.label", description = "@text/action.unifi.generateVouchers.description")
public @ActionOutput(name = "success", type = "java.lang.Boolean") Boolean generateVoucher(
/* @formatter:off */
@ActionInput(name = "expire",
label = "@text/channel-type.config.unifi.guestVouchersGenerate.voucherExpiration.label",
description = "@text/channel-type.config.unifi.guestVouchersGenerate.voucherExpiration.description") @Nullable Integer expire,
@ActionInput(name = "users",
label = "@text/channel-type.config.unifi.guestVouchersGenerate.voucherUsers.label",
description = "@text/channel-type.config.unifi.guestVouchersGenerate.voucherUsers.description") @Nullable Integer users,
@ActionInput(name = "upLimit",
label = "@text/channel-type.config.unifi.guestVouchersGenerate.voucherUpLimit.label",
description = "@text/channel-type.config.unifi.guestVouchersGenerate.voucherUpLimit.description") @Nullable Integer upLimit,
@ActionInput(name = "downLimit",
label = "@text/channel-type.config.unifi.guestVouchersGenerate.voucherDownLimit.label",
description = "@text/channel-type.config.unifi.guestVouchersGenerate.voucherDownLimit.description") @Nullable Integer downLimit,
@ActionInput(name = "dataQuota",
label = "@text/channel-type.config.unifi.guestVouchersGenerate.voucherDataQuota.label",
description = "@text/channel-type.config.unifi.guestVouchersGenerate.voucherDataQuota.description") @Nullable Integer dataQuota) {
/* @formatter:on */
return generateVouchers(1, expire, users, upLimit, downLimit, dataQuota);
}
@RuleAction(label = "@text/action.unifi.generateVouchers.label", description = "@text/action.unifi.generateVouchers.description")
public @ActionOutput(name = "success", type = "java.lang.Boolean") Boolean generateVouchers(
/* @formatter:off */
@ActionInput(name = "count",
label = "@text/channel-type.config.unifi.guestVouchersGenerate.voucherCount.label",
description = "@text/channel-type.config.unifi.guestVouchersGenerate.voucherCount.description") @Nullable Integer count,
@ActionInput(name = "expire",
label = "@text/channel-type.config.unifi.guestVouchersGenerate.voucherExpiration.label",
description = "@text/channel-type.config.unifi.guestVouchersGenerate.voucherExpiration.description") @Nullable Integer expire,
@ActionInput(name = "users",
label = "@text/channel-type.config.unifi.guestVouchersGenerate.voucherUsers.label",
description = "@text/channel-type.config.unifi.guestVouchersGenerate.voucherUsers.description") @Nullable Integer users,
@ActionInput(name = "upLimit",
label = "@text/channel-type.config.unifi.guestVouchersGenerate.voucherUpLimit.label",
description = "@text/channel-type.config.unifi.guestVouchersGenerate.voucherUpLimit.description") @Nullable Integer upLimit,
@ActionInput(name = "downLimit",
label = "@text/channel-type.config.unifi.guestVouchersGenerate.voucherDownLimit.label",
description = "@text/channel-type.config.unifi.guestVouchersGenerate.voucherDownLimit.description") @Nullable Integer downLimit,
@ActionInput(name = "dataQuota",
label = "@text/channel-type.config.unifi.guestVouchersGenerate.voucherDataQuota.label",
description = "@text/channel-type.config.unifi.guestVouchersGenerate.voucherDataQuota.description") @Nullable Integer dataQuota) {
/* @formatter:on */
UniFiSiteThingHandler handler = this.handler;
if (handler == null) {
logger.debug("Could not create guest vouchers, site thing handler not set");
return false;
}
final @Nullable UniFiSite entity = handler.getEntity();
final UniFiController controller = handler.getController();
if (entity == null || controller == null) {
logger.debug("Could not create guest vouchers, site thing error");
return false;
}
try {
controller.generateVouchers(entity, ((count != null) && (count != 0)) ? count : DEFAULT_COUNT,
(expire != null) ? expire : DEFAULT_EXPIRE_MIN, (users != null) ? users : DEFAULT_USERS, upLimit,
downLimit, dataQuota);
} catch (UniFiException e) {
logger.debug("Could not create guest vouchers, uniFi exception", e);
return false;
}
return true;
}
public static boolean generateVoucher(ThingActions actions) {
return UniFiSiteActions.generateVoucher(actions, DEFAULT_EXPIRE_MIN);
}
public static boolean generateVoucher(ThingActions actions, @Nullable Integer expire) {
return UniFiSiteActions.generateVoucher(actions, expire, DEFAULT_USERS);
}
public static boolean generateVoucher(ThingActions actions, @Nullable Integer expire, @Nullable Integer users) {
return UniFiSiteActions.generateVoucher(actions, expire, users, null, null, null);
}
public static boolean generateVoucher(ThingActions actions, @Nullable Integer expire, @Nullable Integer users,
@Nullable Integer upLimit, @Nullable Integer downLimit, @Nullable Integer dataQuota) {
return ((UniFiSiteActions) actions).generateVoucher(expire, users, upLimit, downLimit, dataQuota);
}
public static boolean generateVouchers(ThingActions actions) {
return UniFiSiteActions.generateVouchers(actions, DEFAULT_COUNT);
}
public static boolean generateVouchers(ThingActions actions, @Nullable Integer count) {
return UniFiSiteActions.generateVouchers(actions, count, DEFAULT_EXPIRE_MIN);
}
public static boolean generateVouchers(ThingActions actions, @Nullable Integer count, @Nullable Integer expire) {
return UniFiSiteActions.generateVouchers(actions, count, expire, DEFAULT_USERS);
}
public static boolean generateVouchers(ThingActions actions, @Nullable Integer count, @Nullable Integer expire,
@Nullable Integer users) {
return UniFiSiteActions.generateVouchers(actions, count, expire, users, null, null, null);
}
public static boolean generateVouchers(ThingActions actions, @Nullable Integer count, @Nullable Integer expire,
@Nullable Integer users, @Nullable Integer upLimit, @Nullable Integer downLimit,
@Nullable Integer dataQuota) {
return ((UniFiSiteActions) actions).generateVouchers(count, expire, users, upLimit, downLimit, dataQuota);
}
@RuleAction(label = "@text/action.unifi.revokeVouchers.label", description = "@text/action.unifi.revokeVouchers.description")
public @ActionOutput(name = "success", type = "java.lang.Boolean") Boolean revokeVoucher(
/* @formatter:off */
@ActionInput(name = "voucherCodes", label = "@text/action.unifi.vouchersInputVoucherCodes.label",
description = "@text/action.unifi.vouchersInputVoucherCodes.description") String voucherCode) {
/* @formatter:on */
return revokeVouchers(List.of(voucherCode));
}
@RuleAction(label = "@text/action.unifi.revokeVouchers.label", description = "@text/action.unifi.revokeVouchers.description")
public @ActionOutput(name = "success", type = "java.lang.Boolean") Boolean revokeVouchers(
/* @formatter:off */
@ActionInput(name = "voucherCodes", label = "@text/action.unifi.vouchersInputVoucherCodes.label",
description = "@text/action.unifi.vouchersInputVoucherCodes.description") List<String> voucherCodes) {
/* @formatter:on */
UniFiSiteThingHandler handler = this.handler;
if (handler == null) {
logger.debug("Could not revoke guest vouchers, site thing handler not set");
return false;
}
final @Nullable UniFiSite entity = handler.getEntity();
final UniFiController controller = handler.getController();
if (entity == null || controller == null) {
logger.debug("Could not revoke guest vouchers, site thing error");
return false;
}
// Only keep digits in provided codes, so matching is done correctly. This makes blanks and dashes in the input
// possible, as shown in the UniFi voucher UI.
List<String> cleanCodes = voucherCodes.stream().map(c -> NON_DIGITS_PATTERN.matcher(c).replaceAll(""))
.filter(c -> !c.isEmpty()).toList();
Stream<UniFiVoucher> voucherStream = entity.getCache().getVoucherStreamForSite(entity);
// If no codes provided, revoke all codes
List<UniFiVoucher> vouchers = (voucherCodes.isEmpty() ? voucherStream
: voucherStream.filter(v -> cleanCodes.contains(v.getCode()))).toList();
try {
controller.revokeVouchers(entity, vouchers);
} catch (UniFiException e) {
logger.debug("Could not revoke guest vouchers, uniFi exception", e);
return false;
}
return true;
}
@RuleAction(label = "@text/action.unifi.revokeAllVouchers.label", description = "@text/action.unifi.revokeAllVouchers.description")
public @ActionOutput(name = "success", type = "java.lang.Boolean") Boolean revokeAllVouchers() {
return revokeVouchers(List.of());
}
public static boolean revokeVoucher(ThingActions actions, String voucherCode) {
return revokeVouchers(actions, List.of(voucherCode));
}
public static boolean revokeVouchers(ThingActions actions, List<String> voucherCodes) {
return ((UniFiSiteActions) actions).revokeVouchers(voucherCodes);
}
public static boolean revokeAllVouchers(ThingActions actions) {
return revokeVouchers(actions);
}
public static boolean revokeVouchers(ThingActions actions) {
return revokeVouchers(actions, List.of());
}
@RuleAction(label = "@text/action.unifi.listVouchers.label", description = "@text/action.unifi.listVouchers.description")
public @ActionOutput(name = "vouchers", type = "java.lang.String") String listVouchers() {
UniFiSiteThingHandler handler = this.handler;
if (handler == null) {
logger.debug("Could not list guest vouchers, site thing handler not set");
return "";
}
final @Nullable UniFiSite entity = handler.getEntity();
if (entity == null) {
logger.debug("Could not list guest vouchers, site thing error");
return "";
}
record Voucher(String code, String createTime, Integer duration, Integer quota, Integer used,
Integer qosUsageQuota, Integer qosRateMaxUp, Integer qosRateMaxDown, Boolean qosOverwrite, String note,
String status) {
}
return gson
.toJson(entity.getCache().getVoucherStreamForSite(entity)
.collect(Collectors.mapping(
v -> new Voucher(v.getCode(), v.getCreateTime().toString(), v.getDuration(),
v.getQuota(), v.getUsed(), v.getQosUsageQuota(), v.getQosRateMaxUp(),
v.getQosRateMaxDown(), v.isQosOverwrite(), v.getNote(), v.getStatus()),
Collectors.toList())));
}
public static String listVouchers(ThingActions actions) {
return ((UniFiSiteActions) actions).listVouchers();
}
@Override
public void setThingHandler(ThingHandler handler) {
if (handler instanceof UniFiSiteThingHandler) {
this.handler = (UniFiSiteThingHandler) handler;
}
}
@Override
public @Nullable ThingHandler getThingHandler() {
return handler;
}
}

@ -215,7 +215,7 @@ public class UniFiController {
refresh();
}
public void generateGuestVouchers(final UniFiSite site, final int count, final int expiration, final int users,
public void generateVouchers(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()));
@ -236,6 +236,17 @@ public class UniFiController {
refresh();
}
public void revokeVouchers(final UniFiSite site, final List<UniFiVoucher> vouchers) throws UniFiException {
for (UniFiVoucher voucher : vouchers) {
final UniFiControllerRequest<Void> req = newRequest(Void.class, HttpMethod.POST, gson);
req.setAPIPath(String.format("/api/s/%s/cmd/hotspot", site.getName()));
req.setBodyParameter("cmd", "delete-voucher");
req.setBodyParameter("_id", voucher.getId());
executeRequest(req);
}
refresh();
}
// Internal API
private <T> UniFiControllerRequest<T> newRequest(final Class<T> responseType, final HttpMethod method,

@ -40,8 +40,11 @@ public class UniFiVoucher implements HasId {
private Integer duration;
private Integer quota;
private Integer used;
private boolean qosOverwrite;
private Integer qosUsageQuota;
private Integer qosRateMaxUp;
private Integer qosRateMaxDown;
private boolean qosOverwrite;
private String note;
private String status;
public UniFiVoucher(final UniFiControllerCache cache) {
@ -73,12 +76,24 @@ public class UniFiVoucher implements HasId {
return used;
}
public Integer getQosUsageQuota() {
return qosUsageQuota;
}
public Integer getQosRateMaxUp() {
return qosRateMaxUp;
}
public Integer getQosRateMaxDown() {
return qosRateMaxDown;
}
public boolean isQosOverwrite() {
return qosOverwrite;
}
public Integer getQosUsageQuota() {
return qosUsageQuota;
public String getNote() {
return note;
}
public String getStatus() {
@ -92,7 +107,9 @@ public class UniFiVoucher implements HasId {
@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());
"UniFiVoucher{id: '%s', code: '%s', created: '%s', duration: '%s', quota: '%s', used: '%s', qosUsageQuota: '%s', "
+ "qosRateMaxUp: '%s', qosRateMaxDown: '%s', qosOverwrite: '%s', note: '%s', status: '%s', site: %s}",
id, code, createTime, duration, quota, used, qosUsageQuota, qosRateMaxUp, qosRateMaxDown, qosOverwrite,
note, status, getSite());
}
}

@ -12,8 +12,7 @@
*/
package org.openhab.binding.unifi.internal.handler;
import static org.openhab.core.thing.ThingStatus.OFFLINE;
import static org.openhab.core.thing.ThingStatus.ONLINE;
import static org.openhab.core.thing.ThingStatus.*;
import static org.openhab.core.types.RefreshType.REFRESH;
import java.lang.reflect.ParameterizedType;
@ -81,7 +80,7 @@ public abstract class UniFiBaseThingHandler<E, C> extends BaseThingHandler {
* @return
*/
@SuppressWarnings("null")
private final @Nullable UniFiController getController() {
public final @Nullable UniFiController getController() {
final Bridge bridge = getBridge();
if (bridge != null && bridge.getHandler() != null
&& (bridge.getHandler() instanceof UniFiControllerThingHandler)) {
@ -90,7 +89,8 @@ public abstract class UniFiBaseThingHandler<E, C> extends BaseThingHandler {
return null;
}
private @Nullable E getEntity() {
@Nullable
public E getEntity() {
final UniFiController controller = getController();
return controller == null ? null : getEntity(controller.getCache());
}

@ -12,19 +12,17 @@
*/
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_GUEST_VOUCHER;
import static org.openhab.binding.unifi.internal.UniFiBindingConstants.CHANNEL_GUEST_VOUCHERS_GENERATE;
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.Collection;
import java.util.Collections;
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.action.UniFiSiteActions;
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;
@ -38,6 +36,7 @@ import org.openhab.core.thing.ChannelUID;
import org.openhab.core.thing.Thing;
import org.openhab.core.thing.ThingStatus;
import org.openhab.core.thing.ThingStatusDetail;
import org.openhab.core.thing.binding.ThingHandlerService;
import org.openhab.core.types.Command;
import org.openhab.core.types.State;
import org.openhab.core.types.UnDefType;
@ -127,9 +126,14 @@ public class UniFiSiteThingHandler extends UniFiBaseThingHandler<UniFiSite, UniF
final Integer upLimit = config.getUpLimit();
final Integer downLimit = config.getDownLimit();
final Integer dataQuota = config.getDataQuota();
controller.generateGuestVouchers(entity, count, expire, users, upLimit, downLimit, dataQuota);
controller.generateVouchers(entity, count, expire, users, upLimit, downLimit, dataQuota);
return true;
}
return false;
}
@Override
public Collection<Class<? extends ThingHandlerService>> getServices() {
return Collections.singleton(UniFiSiteActions.class);
}
}

@ -150,6 +150,19 @@ channel-type.config.unifi.poeEnable.mode.description = The value to set when set
channel-type.config.unifi.poeEnable.mode.option.auto = Auto
channel-type.config.unifi.poeEnable.mode.option.pasv24 = 24V
channel-type.config.unifi.poeEnable.mode.option.passthrough = Passthrough
channel-type.config.unifi.guestVouchersGenerate.voucherCount.label = Number
channel-type.config.unifi.guestVouchersGenerate.voucherCount.description = Number of vouchers to create
channel-type.config.unifi.guestVouchersGenerate.voucherExpiration.label = Expiration Time
channel-type.config.unifi.guestVouchersGenerate.voucherExpiration.description = Minutes a voucher is valid after activation
channel-type.config.unifi.guestVouchersGenerate.voucherUsers.label = Users
channel-type.config.unifi.guestVouchersGenerate.voucherUsers.description = Number of users for voucher, 0 if no limit
channel-type.config.unifi.guestVouchersGenerate.voucherUpLimit.label = Upload Speed Limit
channel-type.config.unifi.guestVouchersGenerate.voucherUpLimit.description = Upload speed limit in kbps, no limit if not set
channel-type.config.unifi.guestVouchersGenerate.voucherDownLimit.label = Download Speed Limit
channel-type.config.unifi.guestVouchersGenerate.voucherDownLimit.description = Download speed limit in kbps, no limit if not set
channel-type.config.unifi.guestVouchersGenerate.voucherDataQuota.label = Data Transfer Quota
channel-type.config.unifi.guestVouchersGenerate.voucherDataQuota.description = Data transfer quota in MB per user, no limit if not set
channel-type.config.unifi.guestVouchersGenerate.option.GENERATE = Generate
# status messages
@ -164,3 +177,16 @@ error.thing.offline.configuration_error = You must choose a UniFi Controller for
error.thing.poe.offline.configuration_error = The configuration parameter macAddress must be set and not be empty.
error.thing.poe.offline.nodata_error = No data for the PoE port could be found in the UniFi API data. See TRACE log for actual API data.
error.thing.site.offline.configuration_error = The configuration parameter sid must be set and not be empty.
# actions
action.unifi.generateVouchers.label = Generate
action.unifi.generateVouchers.description = Generate guest voucher(s)
action.unifi.revokeAllVouchers.label = Revoke All
action.unifi.revokeAllVouchers.description = Revoke all guest vouchers
action.unifi.revokeVouchers.label = Revoke
action.unifi.revokeVouchers.description = Revoke guest voucher(s)
action.unifi.vouchersInputVoucherCodes.label = Voucher Code(s)
action.unifi.vouchersInputVoucherCodes.description = Code(s) of voucher(s) to revoke
action.unifi.listVouchers.label = List Vouchers
action.unifi.listVouchers.description = List available vouchers with their parameters and status