[unifi] Added support for UniFi OS (#10041)

Signed-off-by: Mathias Maes <watcherwhale@maes.family>
This commit is contained in:
Mathias 2021-02-04 20:34:38 +01:00 committed by GitHub
parent d452469450
commit 6b4fc99164
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 63 additions and 13 deletions

View 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";
}

View 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 + "}";
}
}

View 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();

View 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;
}

View 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) {

View File

@ -21,6 +21,10 @@
<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>