]> git.basschouten.com Git - openhab-addons.git/commitdiff
[unifi] Added support for UniFi OS (#10041)
authorMathias <mathias.maes.mm@gmail.com>
Thu, 4 Feb 2021 19:34:38 +0000 (20:34 +0100)
committerGitHub <noreply@github.com>
Thu, 4 Feb 2021 19:34:38 +0000 (20:34 +0100)
Signed-off-by: Mathias Maes <watcherwhale@maes.family>
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/UniFiControllerThingConfig.java
bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/model/UniFiController.java
bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/model/UniFiControllerRequest.java
bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/handler/UniFiControllerThingHandler.java
bundles/org.openhab.binding.unifi/src/main/resources/OH-INF/thing/thing-types.xml

index 739782b18061b63361d3068f888171342f1326b6..3c3fe621185c773adfc3f05edb36c5eac6febed7 100644 (file)
@@ -53,6 +53,7 @@ public class UniFiBindingConstants {
     public static final String PARAMETER_PORT = "port";
     public static final String PARAMETER_USERNAME = "username";
     public static final String PARAMETER_PASSWORD = "password";
+    public static final String PARAMETER_UNIFIOS = "unifios";
     public static final String PARAMETER_SITE = "site";
     public static final String PARAMETER_CID = "cid";
 }
index 78d80fe72edc238e54c8539949a161aefd3ab276..4f05ba2980d8a9e1d57205be87abb0947712675d 100644 (file)
@@ -33,6 +33,8 @@ public class UniFiControllerThingConfig {
 
     private int refresh = 10;
 
+    private boolean unifios = false;
+
     public String getHost() {
         return host;
     }
@@ -53,6 +55,10 @@ public class UniFiControllerThingConfig {
         return refresh;
     }
 
+    public boolean isUniFiOS() {
+        return unifios;
+    }
+
     public boolean isValid() {
         return StringUtils.isNotBlank(host) && StringUtils.isNotBlank(username) && StringUtils.isNotBlank(password);
     }
@@ -60,6 +66,6 @@ public class UniFiControllerThingConfig {
     @Override
     public String toString() {
         return "UniFiControllerConfig{host = " + host + ", port = " + port + ", username = " + username
-                + ", password = *****, refresh = " + refresh + "}";
+                + ", password = *****, refresh = " + refresh + ", unifios = " + unifios + "}";
     }
 }
index 967e2943f037a570cb0b1e5a7b206ba402e96249..0c47a7a3b0d57a47ae7a7be6d8e172206bbf11b4 100644 (file)
@@ -65,14 +65,21 @@ public class UniFiController {
 
     private final String password;
 
+    private final boolean unifios;
+
+    private String csrfToken;
+
     private final Gson gson;
 
-    public UniFiController(HttpClient httpClient, String host, int port, String username, String password) {
+    public UniFiController(HttpClient httpClient, String host, int port, String username, String password,
+            boolean unifios) {
         this.httpClient = httpClient;
         this.host = host;
         this.port = port;
         this.username = username;
         this.password = password;
+        this.unifios = unifios;
+        this.csrfToken = "";
         UniFiSiteInstanceCreator siteInstanceCreator = new UniFiSiteInstanceCreator(this);
         UniFiDeviceInstanceCreator deviceInstanceCreator = new UniFiDeviceInstanceCreator(this);
         UniFiClientInstanceCreator clientInstanceCreator = new UniFiClientInstanceCreator(this);
@@ -96,8 +103,10 @@ public class UniFiController {
     }
 
     public void login() throws UniFiException {
+        csrfToken = "";
+
         UniFiControllerRequest<Void> req = newRequest(Void.class);
-        req.setPath("/api/login");
+        req.setPath(unifios ? "/api/auth/login" : "/api/login");
         req.setBodyParameter("username", username);
         req.setBodyParameter("password", password);
         // scurb: Changed strict = false to make blocking feature work
@@ -107,8 +116,9 @@ public class UniFiController {
     }
 
     public void logout() throws UniFiException {
+        csrfToken = "";
         UniFiControllerRequest<Void> req = newRequest(Void.class);
-        req.setPath("/logout");
+        req.setPath(unifios ? "/api/auth/logout" : "/logout");
         executeRequest(req);
     }
 
@@ -172,7 +182,7 @@ public class UniFiController {
 
     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.setAPIPath("/api/s/" + client.getSite().getName() + "/cmd/stamgr");
         req.setBodyParameter("cmd", blocked ? "block-sta" : "unblock-sta");
         req.setBodyParameter("mac", client.getMac());
         executeRequest(req);
@@ -180,7 +190,7 @@ public class UniFiController {
 
     protected void reconnect(UniFiClient client) throws UniFiException {
         UniFiControllerRequest<Void> req = newRequest(Void.class);
-        req.setPath("/api/s/" + client.getSite().getName() + "/cmd/stamgr");
+        req.setAPIPath("/api/s/" + client.getSite().getName() + "/cmd/stamgr");
         req.setBodyParameter("cmd", "kick-sta");
         req.setBodyParameter("mac", client.getMac());
         executeRequest(req);
@@ -189,13 +199,14 @@ public class UniFiController {
     // Internal API
 
     private <T> UniFiControllerRequest<T> newRequest(Class<T> responseType) {
-        return new UniFiControllerRequest<>(responseType, gson, httpClient, host, port);
+        return new UniFiControllerRequest<>(responseType, gson, httpClient, host, port, csrfToken, unifios);
     }
 
     private <T> @Nullable T executeRequest(UniFiControllerRequest<T> request) throws UniFiException {
         T result;
         try {
             result = request.execute();
+            csrfToken = request.getCsrfToken();
         } catch (UniFiExpiredSessionException e) {
             login();
             result = executeRequest(request);
@@ -208,7 +219,7 @@ public class UniFiController {
 
     private UniFiSiteCache getSites() throws UniFiException {
         UniFiControllerRequest<UniFiSite[]> req = newRequest(UniFiSite[].class);
-        req.setPath("/api/self/sites");
+        req.setAPIPath("/api/self/sites");
         UniFiSite[] sites = executeRequest(req);
         UniFiSiteCache cache = new UniFiSiteCache();
         if (sites != null) {
@@ -231,7 +242,7 @@ public class UniFiController {
 
     private UniFiDeviceCache getDevices(UniFiSite site) throws UniFiException {
         UniFiControllerRequest<UniFiDevice[]> req = newRequest(UniFiDevice[].class);
-        req.setPath("/api/s/" + site.getName() + "/stat/device");
+        req.setAPIPath("/api/s/" + site.getName() + "/stat/device");
         UniFiDevice[] devices = executeRequest(req);
         UniFiDeviceCache cache = new UniFiDeviceCache();
         if (devices != null) {
@@ -254,7 +265,7 @@ public class UniFiController {
 
     private UniFiClientCache getClients(UniFiSite site) throws UniFiException {
         UniFiControllerRequest<UniFiClient[]> req = newRequest(UniFiClient[].class);
-        req.setPath("/api/s/" + site.getName() + "/stat/sta");
+        req.setAPIPath("/api/s/" + site.getName() + "/stat/sta");
         UniFiClient[] clients = executeRequest(req);
         UniFiClientCache cache = new UniFiClientCache();
         if (clients != null) {
@@ -277,7 +288,7 @@ public class UniFiController {
 
     private UniFiClientCache getInsights(UniFiSite site) throws UniFiException {
         UniFiControllerRequest<UniFiClient[]> req = newRequest(UniFiClient[].class);
-        req.setPath("/api/s/" + site.getName() + "/stat/alluser");
+        req.setAPIPath("/api/s/" + site.getName() + "/stat/alluser");
         req.setQueryParameter("within", 168); // scurb: Changed to 7 days.
         UniFiClient[] clients = executeRequest(req);
         UniFiClientCache cache = new UniFiClientCache();
index a3bd6a76a6d98eb8e70805c8a872279d1f61773f..a56d955f412bb31b5dd7349ba580a9b618d8ffc6 100644 (file)
@@ -83,6 +83,10 @@ public class UniFiControllerRequest<T> {
 
     private String path = "/";
 
+    private final boolean unifios;
+
+    private String csrfToken;
+
     private Map<String, String> queryParameters = new HashMap<>();
 
     private Map<String, String> bodyParameters = new HashMap<>();
@@ -91,12 +95,23 @@ public class UniFiControllerRequest<T> {
 
     // Public API
 
-    public UniFiControllerRequest(Class<T> resultType, Gson gson, HttpClient httpClient, String host, int port) {
+    public UniFiControllerRequest(Class<T> resultType, Gson gson, HttpClient httpClient, String host, int port,
+            String csrfToken, boolean unifios) {
         this.resultType = resultType;
         this.gson = gson;
         this.httpClient = httpClient;
         this.host = host;
         this.port = port;
+        this.csrfToken = csrfToken;
+        this.unifios = unifios;
+    }
+
+    public void setAPIPath(String relativePath) {
+        if (unifios) {
+            this.path = "/proxy/network" + relativePath;
+        } else {
+            this.path = relativePath;
+        }
     }
 
     public void setPath(String path) {
@@ -136,6 +151,11 @@ public class UniFiControllerRequest<T> {
                 if (logger.isTraceEnabled()) {
                     logger.trace("<< {} {} \n{}", status, HttpStatus.getMessage(status), prettyPrintJson(content));
                 }
+
+                String csrfToken = response.getHeaders().get("X-CSRF-Token");
+                if (csrfToken != null && !csrfToken.isEmpty()) {
+                    this.csrfToken = csrfToken;
+                }
                 break;
             case HttpStatus.BAD_REQUEST_400:
                 throw new UniFiInvalidCredentialsException("Invalid Credentials");
@@ -184,6 +204,10 @@ public class UniFiControllerRequest<T> {
         return response;
     }
 
+    public String getCsrfToken() {
+        return csrfToken;
+    }
+
     private Request newRequest() {
         HttpMethod method = bodyParameters.isEmpty() ? HttpMethod.GET : HttpMethod.POST;
         HttpURI uri = new HttpURI(HttpScheme.HTTPS.asString(), host, port, path);
@@ -198,6 +222,10 @@ public class UniFiControllerRequest<T> {
                     StandardCharsets.UTF_8);
             request = request.content(content);
         }
+
+        if (!csrfToken.isEmpty())
+            request.header("x-csrf-token", this.csrfToken);
+
         return request;
     }
 
index 183cabdba2c92895582c9bdd3f9e6f3e7f8a1266..56376136baabe65a7c5dc7754e9b5773ca8bb5ae 100644 (file)
@@ -88,7 +88,7 @@ public class UniFiControllerThingHandler extends BaseBridgeHandler {
         logger.debug("Initializing the UniFi Controller Handler with config = {}", config);
         try {
             controller = new UniFiController(httpClient, config.getHost(), config.getPort(), config.getUsername(),
-                    config.getPassword());
+                    config.getPassword(), config.isUniFiOS());
             controller.start();
             updateStatus(ONLINE);
         } catch (UniFiInvalidHostException e) {
index 4ceb58792d60680dd694745041ff391e0f7bb502..7632c4b5a1c27116a43ac3867b368016dc2959b8 100644 (file)
                                <description>Port of the UniFi Controller</description>
                                <default>8443</default>
                        </parameter>
+                       <parameter name="unifios" type="boolean" required="true">
+                               <label>UniFi OS</label>
+                               <description>If the UniFi Controller is running on UniFi OS.</description>
+                       </parameter>
                        <parameter name="username" type="text" required="true">
                                <label>Username</label>
                                <description>The username to access the UniFi Controller.</description>