]> git.basschouten.com Git - openhab-addons.git/blob
64c8838f555a49f6056b62a9c130409908fe751a
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2024 Contributors to the openHAB project
3  *
4  * See the NOTICE file(s) distributed with this work for additional
5  * information.
6  *
7  * This program and the accompanying materials are made available under the
8  * terms of the Eclipse Public License 2.0 which is available at
9  * http://www.eclipse.org/legal/epl-2.0
10  *
11  * SPDX-License-Identifier: EPL-2.0
12  */
13 package org.openhab.binding.unifi.internal.action;
14
15 import java.util.List;
16 import java.util.regex.Pattern;
17 import java.util.stream.Collectors;
18 import java.util.stream.Stream;
19
20 import org.eclipse.jdt.annotation.NonNullByDefault;
21 import org.eclipse.jdt.annotation.Nullable;
22 import org.openhab.binding.unifi.internal.api.UniFiController;
23 import org.openhab.binding.unifi.internal.api.UniFiException;
24 import org.openhab.binding.unifi.internal.api.dto.UniFiSite;
25 import org.openhab.binding.unifi.internal.api.dto.UniFiVoucher;
26 import org.openhab.binding.unifi.internal.handler.UniFiSiteThingHandler;
27 import org.openhab.core.automation.annotation.ActionInput;
28 import org.openhab.core.automation.annotation.ActionOutput;
29 import org.openhab.core.automation.annotation.RuleAction;
30 import org.openhab.core.thing.binding.ThingActions;
31 import org.openhab.core.thing.binding.ThingActionsScope;
32 import org.openhab.core.thing.binding.ThingHandler;
33 import org.osgi.service.component.annotations.Component;
34 import org.osgi.service.component.annotations.ServiceScope;
35 import org.slf4j.Logger;
36 import org.slf4j.LoggerFactory;
37
38 import com.google.gson.Gson;
39
40 /**
41  * The {@link UniFiSiteActions} class defines rule actions for creating guest hotspot vouchers
42  *
43  * @author Mark Herwege - Initial contribution
44  */
45 @Component(scope = ServiceScope.PROTOTYPE, service = UniFiSiteActions.class)
46 @ThingActionsScope(name = "unifi")
47 @NonNullByDefault
48 public class UniFiSiteActions implements ThingActions {
49
50     private static final int DEFAULT_COUNT = 1;
51     private static final int DEFAULT_EXPIRE_MIN = 1440;
52     private static final int DEFAULT_USERS = 1;
53
54     private static final Pattern NON_DIGITS_PATTERN = Pattern.compile("\\D+");
55
56     private final Logger logger = LoggerFactory.getLogger(UniFiSiteActions.class);
57
58     private @Nullable UniFiSiteThingHandler handler;
59     private final Gson gson = new Gson();
60
61     @RuleAction(label = "@text/action.unifi.generateVouchers.label", description = "@text/action.unifi.generateVouchers.description")
62     public @ActionOutput(name = "success", type = "java.lang.Boolean") Boolean generateVoucher(
63     /* @formatter:off */
64             @ActionInput(name = "expire",
65                 label = "@text/channel-type.config.unifi.guestVouchersGenerate.voucherExpiration.label",
66                 description = "@text/channel-type.config.unifi.guestVouchersGenerate.voucherExpiration.description") @Nullable Integer expire,
67             @ActionInput(name = "users",
68                 label = "@text/channel-type.config.unifi.guestVouchersGenerate.voucherUsers.label",
69                 description = "@text/channel-type.config.unifi.guestVouchersGenerate.voucherUsers.description") @Nullable Integer users,
70             @ActionInput(name = "upLimit",
71                 label = "@text/channel-type.config.unifi.guestVouchersGenerate.voucherUpLimit.label",
72                 description = "@text/channel-type.config.unifi.guestVouchersGenerate.voucherUpLimit.description") @Nullable Integer upLimit,
73             @ActionInput(name = "downLimit",
74                 label = "@text/channel-type.config.unifi.guestVouchersGenerate.voucherDownLimit.label",
75                 description = "@text/channel-type.config.unifi.guestVouchersGenerate.voucherDownLimit.description") @Nullable Integer downLimit,
76             @ActionInput(name = "dataQuota",
77                 label = "@text/channel-type.config.unifi.guestVouchersGenerate.voucherDataQuota.label",
78                 description = "@text/channel-type.config.unifi.guestVouchersGenerate.voucherDataQuota.description") @Nullable Integer dataQuota) {
79     /* @formatter:on */
80         return generateVouchers(1, expire, users, upLimit, downLimit, dataQuota);
81     }
82
83     @RuleAction(label = "@text/action.unifi.generateVouchers.label", description = "@text/action.unifi.generateVouchers.description")
84     public @ActionOutput(name = "success", type = "java.lang.Boolean") Boolean generateVouchers(
85     /* @formatter:off */
86             @ActionInput(name = "count",
87                 label = "@text/channel-type.config.unifi.guestVouchersGenerate.voucherCount.label",
88                 description = "@text/channel-type.config.unifi.guestVouchersGenerate.voucherCount.description") @Nullable Integer count,
89             @ActionInput(name = "expire",
90                 label = "@text/channel-type.config.unifi.guestVouchersGenerate.voucherExpiration.label",
91                 description = "@text/channel-type.config.unifi.guestVouchersGenerate.voucherExpiration.description") @Nullable Integer expire,
92             @ActionInput(name = "users",
93                 label = "@text/channel-type.config.unifi.guestVouchersGenerate.voucherUsers.label",
94                 description = "@text/channel-type.config.unifi.guestVouchersGenerate.voucherUsers.description") @Nullable Integer users,
95             @ActionInput(name = "upLimit",
96                 label = "@text/channel-type.config.unifi.guestVouchersGenerate.voucherUpLimit.label",
97                 description = "@text/channel-type.config.unifi.guestVouchersGenerate.voucherUpLimit.description") @Nullable Integer upLimit,
98             @ActionInput(name = "downLimit",
99                 label = "@text/channel-type.config.unifi.guestVouchersGenerate.voucherDownLimit.label",
100                 description = "@text/channel-type.config.unifi.guestVouchersGenerate.voucherDownLimit.description") @Nullable Integer downLimit,
101             @ActionInput(name = "dataQuota",
102                 label = "@text/channel-type.config.unifi.guestVouchersGenerate.voucherDataQuota.label",
103                 description = "@text/channel-type.config.unifi.guestVouchersGenerate.voucherDataQuota.description") @Nullable Integer dataQuota) {
104     /* @formatter:on */
105         UniFiSiteThingHandler handler = this.handler;
106         if (handler == null) {
107             logger.debug("Could not create guest vouchers, site thing handler not set");
108             return false;
109         }
110         final @Nullable UniFiSite entity = handler.getEntity();
111         final UniFiController controller = handler.getController();
112         if (entity == null || controller == null) {
113             logger.debug("Could not create guest vouchers, site thing error");
114             return false;
115         }
116         try {
117             controller.generateVouchers(entity, ((count != null) && (count != 0)) ? count : DEFAULT_COUNT,
118                     (expire != null) ? expire : DEFAULT_EXPIRE_MIN, (users != null) ? users : DEFAULT_USERS, upLimit,
119                     downLimit, dataQuota);
120         } catch (UniFiException e) {
121             logger.debug("Could not create guest vouchers, uniFi exception", e);
122             return false;
123         }
124         return true;
125     }
126
127     public static boolean generateVoucher(ThingActions actions) {
128         return UniFiSiteActions.generateVoucher(actions, DEFAULT_EXPIRE_MIN);
129     }
130
131     public static boolean generateVoucher(ThingActions actions, @Nullable Integer expire) {
132         return UniFiSiteActions.generateVoucher(actions, expire, DEFAULT_USERS);
133     }
134
135     public static boolean generateVoucher(ThingActions actions, @Nullable Integer expire, @Nullable Integer users) {
136         return UniFiSiteActions.generateVoucher(actions, expire, users, null, null, null);
137     }
138
139     public static boolean generateVoucher(ThingActions actions, @Nullable Integer expire, @Nullable Integer users,
140             @Nullable Integer upLimit, @Nullable Integer downLimit, @Nullable Integer dataQuota) {
141         return ((UniFiSiteActions) actions).generateVoucher(expire, users, upLimit, downLimit, dataQuota);
142     }
143
144     public static boolean generateVouchers(ThingActions actions) {
145         return UniFiSiteActions.generateVouchers(actions, DEFAULT_COUNT);
146     }
147
148     public static boolean generateVouchers(ThingActions actions, @Nullable Integer count) {
149         return UniFiSiteActions.generateVouchers(actions, count, DEFAULT_EXPIRE_MIN);
150     }
151
152     public static boolean generateVouchers(ThingActions actions, @Nullable Integer count, @Nullable Integer expire) {
153         return UniFiSiteActions.generateVouchers(actions, count, expire, DEFAULT_USERS);
154     }
155
156     public static boolean generateVouchers(ThingActions actions, @Nullable Integer count, @Nullable Integer expire,
157             @Nullable Integer users) {
158         return UniFiSiteActions.generateVouchers(actions, count, expire, users, null, null, null);
159     }
160
161     public static boolean generateVouchers(ThingActions actions, @Nullable Integer count, @Nullable Integer expire,
162             @Nullable Integer users, @Nullable Integer upLimit, @Nullable Integer downLimit,
163             @Nullable Integer dataQuota) {
164         return ((UniFiSiteActions) actions).generateVouchers(count, expire, users, upLimit, downLimit, dataQuota);
165     }
166
167     @RuleAction(label = "@text/action.unifi.revokeVouchers.label", description = "@text/action.unifi.revokeVouchers.description")
168     public @ActionOutput(name = "success", type = "java.lang.Boolean") Boolean revokeVoucher(
169     /* @formatter:off */
170             @ActionInput(name = "voucherCodes", label = "@text/action.unifi.vouchersInputVoucherCodes.label",
171                 description = "@text/action.unifi.vouchersInputVoucherCodes.description") String voucherCode) {
172     /* @formatter:on */
173         return revokeVouchers(List.of(voucherCode));
174     }
175
176     @RuleAction(label = "@text/action.unifi.revokeVouchers.label", description = "@text/action.unifi.revokeVouchers.description")
177     public @ActionOutput(name = "success", type = "java.lang.Boolean") Boolean revokeVouchers(
178     /* @formatter:off */
179             @ActionInput(name = "voucherCodes", label = "@text/action.unifi.vouchersInputVoucherCodes.label",
180                 description = "@text/action.unifi.vouchersInputVoucherCodes.description") List<String> voucherCodes) {
181     /* @formatter:on */
182         UniFiSiteThingHandler handler = this.handler;
183         if (handler == null) {
184             logger.debug("Could not revoke guest vouchers, site thing handler not set");
185             return false;
186         }
187         final @Nullable UniFiSite entity = handler.getEntity();
188         final UniFiController controller = handler.getController();
189         if (entity == null || controller == null) {
190             logger.debug("Could not revoke guest vouchers, site thing error");
191             return false;
192         }
193
194         // Only keep digits in provided codes, so matching is done correctly. This makes blanks and dashes in the input
195         // possible, as shown in the UniFi voucher UI.
196         List<String> cleanCodes = voucherCodes.stream().map(c -> NON_DIGITS_PATTERN.matcher(c).replaceAll(""))
197                 .filter(c -> !c.isEmpty()).toList();
198         Stream<UniFiVoucher> voucherStream = entity.getCache().getVoucherStreamForSite(entity);
199         // If no codes provided, revoke all codes
200         List<UniFiVoucher> vouchers = (voucherCodes.isEmpty() ? voucherStream
201                 : voucherStream.filter(v -> cleanCodes.contains(v.getCode()))).toList();
202         try {
203             controller.revokeVouchers(entity, vouchers);
204         } catch (UniFiException e) {
205             logger.debug("Could not revoke guest vouchers, uniFi exception", e);
206             return false;
207         }
208         return true;
209     }
210
211     @RuleAction(label = "@text/action.unifi.revokeAllVouchers.label", description = "@text/action.unifi.revokeAllVouchers.description")
212     public @ActionOutput(name = "success", type = "java.lang.Boolean") Boolean revokeAllVouchers() {
213         return revokeVouchers(List.of());
214     }
215
216     public static boolean revokeVoucher(ThingActions actions, String voucherCode) {
217         return revokeVouchers(actions, List.of(voucherCode));
218     }
219
220     public static boolean revokeVouchers(ThingActions actions, List<String> voucherCodes) {
221         return ((UniFiSiteActions) actions).revokeVouchers(voucherCodes);
222     }
223
224     public static boolean revokeAllVouchers(ThingActions actions) {
225         return revokeVouchers(actions);
226     }
227
228     public static boolean revokeVouchers(ThingActions actions) {
229         return revokeVouchers(actions, List.of());
230     }
231
232     @RuleAction(label = "@text/action.unifi.listVouchers.label", description = "@text/action.unifi.listVouchers.description")
233     public @ActionOutput(name = "vouchers", type = "java.lang.String") String listVouchers() {
234         UniFiSiteThingHandler handler = this.handler;
235         if (handler == null) {
236             logger.debug("Could not list guest vouchers, site thing handler not set");
237             return "";
238         }
239         final @Nullable UniFiSite entity = handler.getEntity();
240         if (entity == null) {
241             logger.debug("Could not list guest vouchers, site thing error");
242             return "";
243         }
244
245         record Voucher(String code, String createTime, Integer duration, Integer quota, Integer used,
246                 Integer qosUsageQuota, Integer qosRateMaxUp, Integer qosRateMaxDown, Boolean qosOverwrite, String note,
247                 String status) {
248         }
249
250         return gson
251                 .toJson(entity.getCache().getVoucherStreamForSite(entity)
252                         .collect(Collectors.mapping(
253                                 v -> new Voucher(v.getCode(), v.getCreateTime().toString(), v.getDuration(),
254                                         v.getQuota(), v.getUsed(), v.getQosUsageQuota(), v.getQosRateMaxUp(),
255                                         v.getQosRateMaxDown(), v.isQosOverwrite(), v.getNote(), v.getStatus()),
256                                 Collectors.toList())));
257     }
258
259     public static String listVouchers(ThingActions actions) {
260         return ((UniFiSiteActions) actions).listVouchers();
261     }
262
263     @Override
264     public void setThingHandler(ThingHandler handler) {
265         if (handler instanceof UniFiSiteThingHandler siteThingHandler) {
266             this.handler = siteThingHandler;
267         }
268     }
269
270     @Override
271     public @Nullable ThingHandler getThingHandler() {
272         return handler;
273     }
274 }