[unifi] Added support for UniFi OS (#10041)
Signed-off-by: Mathias Maes <watcherwhale@maes.family>
This commit is contained in:
parent
d452469450
commit
6b4fc99164
|
@ -53,6 +53,7 @@ public class UniFiBindingConstants {
|
||||||
public static final String PARAMETER_PORT = "port";
|
public static final String PARAMETER_PORT = "port";
|
||||||
public static final String PARAMETER_USERNAME = "username";
|
public static final String PARAMETER_USERNAME = "username";
|
||||||
public static final String PARAMETER_PASSWORD = "password";
|
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_SITE = "site";
|
||||||
public static final String PARAMETER_CID = "cid";
|
public static final String PARAMETER_CID = "cid";
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,6 +33,8 @@ public class UniFiControllerThingConfig {
|
||||||
|
|
||||||
private int refresh = 10;
|
private int refresh = 10;
|
||||||
|
|
||||||
|
private boolean unifios = false;
|
||||||
|
|
||||||
public String getHost() {
|
public String getHost() {
|
||||||
return host;
|
return host;
|
||||||
}
|
}
|
||||||
|
@ -53,6 +55,10 @@ public class UniFiControllerThingConfig {
|
||||||
return refresh;
|
return refresh;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isUniFiOS() {
|
||||||
|
return unifios;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isValid() {
|
public boolean isValid() {
|
||||||
return StringUtils.isNotBlank(host) && StringUtils.isNotBlank(username) && StringUtils.isNotBlank(password);
|
return StringUtils.isNotBlank(host) && StringUtils.isNotBlank(username) && StringUtils.isNotBlank(password);
|
||||||
}
|
}
|
||||||
|
@ -60,6 +66,6 @@ public class UniFiControllerThingConfig {
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "UniFiControllerConfig{host = " + host + ", port = " + port + ", username = " + username
|
return "UniFiControllerConfig{host = " + host + ", port = " + port + ", username = " + username
|
||||||
+ ", password = *****, refresh = " + refresh + "}";
|
+ ", password = *****, refresh = " + refresh + ", unifios = " + unifios + "}";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,14 +65,21 @@ public class UniFiController {
|
||||||
|
|
||||||
private final String password;
|
private final String password;
|
||||||
|
|
||||||
|
private final boolean unifios;
|
||||||
|
|
||||||
|
private String csrfToken;
|
||||||
|
|
||||||
private final Gson gson;
|
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.httpClient = httpClient;
|
||||||
this.host = host;
|
this.host = host;
|
||||||
this.port = port;
|
this.port = port;
|
||||||
this.username = username;
|
this.username = username;
|
||||||
this.password = password;
|
this.password = password;
|
||||||
|
this.unifios = unifios;
|
||||||
|
this.csrfToken = "";
|
||||||
UniFiSiteInstanceCreator siteInstanceCreator = new UniFiSiteInstanceCreator(this);
|
UniFiSiteInstanceCreator siteInstanceCreator = new UniFiSiteInstanceCreator(this);
|
||||||
UniFiDeviceInstanceCreator deviceInstanceCreator = new UniFiDeviceInstanceCreator(this);
|
UniFiDeviceInstanceCreator deviceInstanceCreator = new UniFiDeviceInstanceCreator(this);
|
||||||
UniFiClientInstanceCreator clientInstanceCreator = new UniFiClientInstanceCreator(this);
|
UniFiClientInstanceCreator clientInstanceCreator = new UniFiClientInstanceCreator(this);
|
||||||
|
@ -96,8 +103,10 @@ public class UniFiController {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void login() throws UniFiException {
|
public void login() throws UniFiException {
|
||||||
|
csrfToken = "";
|
||||||
|
|
||||||
UniFiControllerRequest<Void> req = newRequest(Void.class);
|
UniFiControllerRequest<Void> req = newRequest(Void.class);
|
||||||
req.setPath("/api/login");
|
req.setPath(unifios ? "/api/auth/login" : "/api/login");
|
||||||
req.setBodyParameter("username", username);
|
req.setBodyParameter("username", username);
|
||||||
req.setBodyParameter("password", password);
|
req.setBodyParameter("password", password);
|
||||||
// scurb: Changed strict = false to make blocking feature work
|
// scurb: Changed strict = false to make blocking feature work
|
||||||
|
@ -107,8 +116,9 @@ public class UniFiController {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void logout() throws UniFiException {
|
public void logout() throws UniFiException {
|
||||||
|
csrfToken = "";
|
||||||
UniFiControllerRequest<Void> req = newRequest(Void.class);
|
UniFiControllerRequest<Void> req = newRequest(Void.class);
|
||||||
req.setPath("/logout");
|
req.setPath(unifios ? "/api/auth/logout" : "/logout");
|
||||||
executeRequest(req);
|
executeRequest(req);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -172,7 +182,7 @@ public class UniFiController {
|
||||||
|
|
||||||
protected void block(UniFiClient client, boolean blocked) throws UniFiException {
|
protected void block(UniFiClient client, boolean blocked) throws UniFiException {
|
||||||
UniFiControllerRequest<Void> req = newRequest(Void.class);
|
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("cmd", blocked ? "block-sta" : "unblock-sta");
|
||||||
req.setBodyParameter("mac", client.getMac());
|
req.setBodyParameter("mac", client.getMac());
|
||||||
executeRequest(req);
|
executeRequest(req);
|
||||||
|
@ -180,7 +190,7 @@ public class UniFiController {
|
||||||
|
|
||||||
protected void reconnect(UniFiClient client) throws UniFiException {
|
protected void reconnect(UniFiClient client) throws UniFiException {
|
||||||
UniFiControllerRequest<Void> req = newRequest(Void.class);
|
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("cmd", "kick-sta");
|
||||||
req.setBodyParameter("mac", client.getMac());
|
req.setBodyParameter("mac", client.getMac());
|
||||||
executeRequest(req);
|
executeRequest(req);
|
||||||
|
@ -189,13 +199,14 @@ public class UniFiController {
|
||||||
// Internal API
|
// Internal API
|
||||||
|
|
||||||
private <T> UniFiControllerRequest<T> newRequest(Class<T> responseType) {
|
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 {
|
private <T> @Nullable T executeRequest(UniFiControllerRequest<T> request) throws UniFiException {
|
||||||
T result;
|
T result;
|
||||||
try {
|
try {
|
||||||
result = request.execute();
|
result = request.execute();
|
||||||
|
csrfToken = request.getCsrfToken();
|
||||||
} catch (UniFiExpiredSessionException e) {
|
} catch (UniFiExpiredSessionException e) {
|
||||||
login();
|
login();
|
||||||
result = executeRequest(request);
|
result = executeRequest(request);
|
||||||
|
@ -208,7 +219,7 @@ public class UniFiController {
|
||||||
|
|
||||||
private UniFiSiteCache getSites() throws UniFiException {
|
private UniFiSiteCache getSites() throws UniFiException {
|
||||||
UniFiControllerRequest<UniFiSite[]> req = newRequest(UniFiSite[].class);
|
UniFiControllerRequest<UniFiSite[]> req = newRequest(UniFiSite[].class);
|
||||||
req.setPath("/api/self/sites");
|
req.setAPIPath("/api/self/sites");
|
||||||
UniFiSite[] sites = executeRequest(req);
|
UniFiSite[] sites = executeRequest(req);
|
||||||
UniFiSiteCache cache = new UniFiSiteCache();
|
UniFiSiteCache cache = new UniFiSiteCache();
|
||||||
if (sites != null) {
|
if (sites != null) {
|
||||||
|
@ -231,7 +242,7 @@ public class UniFiController {
|
||||||
|
|
||||||
private UniFiDeviceCache getDevices(UniFiSite site) throws UniFiException {
|
private UniFiDeviceCache getDevices(UniFiSite site) throws UniFiException {
|
||||||
UniFiControllerRequest<UniFiDevice[]> req = newRequest(UniFiDevice[].class);
|
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);
|
UniFiDevice[] devices = executeRequest(req);
|
||||||
UniFiDeviceCache cache = new UniFiDeviceCache();
|
UniFiDeviceCache cache = new UniFiDeviceCache();
|
||||||
if (devices != null) {
|
if (devices != null) {
|
||||||
|
@ -254,7 +265,7 @@ public class UniFiController {
|
||||||
|
|
||||||
private UniFiClientCache getClients(UniFiSite site) throws UniFiException {
|
private UniFiClientCache getClients(UniFiSite site) throws UniFiException {
|
||||||
UniFiControllerRequest<UniFiClient[]> req = newRequest(UniFiClient[].class);
|
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);
|
UniFiClient[] clients = executeRequest(req);
|
||||||
UniFiClientCache cache = new UniFiClientCache();
|
UniFiClientCache cache = new UniFiClientCache();
|
||||||
if (clients != null) {
|
if (clients != null) {
|
||||||
|
@ -277,7 +288,7 @@ public class UniFiController {
|
||||||
|
|
||||||
private UniFiClientCache getInsights(UniFiSite site) throws UniFiException {
|
private UniFiClientCache getInsights(UniFiSite site) throws UniFiException {
|
||||||
UniFiControllerRequest<UniFiClient[]> req = newRequest(UniFiClient[].class);
|
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.
|
req.setQueryParameter("within", 168); // scurb: Changed to 7 days.
|
||||||
UniFiClient[] clients = executeRequest(req);
|
UniFiClient[] clients = executeRequest(req);
|
||||||
UniFiClientCache cache = new UniFiClientCache();
|
UniFiClientCache cache = new UniFiClientCache();
|
||||||
|
|
|
@ -83,6 +83,10 @@ public class UniFiControllerRequest<T> {
|
||||||
|
|
||||||
private String path = "/";
|
private String path = "/";
|
||||||
|
|
||||||
|
private final boolean unifios;
|
||||||
|
|
||||||
|
private String csrfToken;
|
||||||
|
|
||||||
private Map<String, String> queryParameters = new HashMap<>();
|
private Map<String, String> queryParameters = new HashMap<>();
|
||||||
|
|
||||||
private Map<String, String> bodyParameters = new HashMap<>();
|
private Map<String, String> bodyParameters = new HashMap<>();
|
||||||
|
@ -91,12 +95,23 @@ public class UniFiControllerRequest<T> {
|
||||||
|
|
||||||
// Public API
|
// 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.resultType = resultType;
|
||||||
this.gson = gson;
|
this.gson = gson;
|
||||||
this.httpClient = httpClient;
|
this.httpClient = httpClient;
|
||||||
this.host = host;
|
this.host = host;
|
||||||
this.port = port;
|
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) {
|
public void setPath(String path) {
|
||||||
|
@ -136,6 +151,11 @@ public class UniFiControllerRequest<T> {
|
||||||
if (logger.isTraceEnabled()) {
|
if (logger.isTraceEnabled()) {
|
||||||
logger.trace("<< {} {} \n{}", status, HttpStatus.getMessage(status), prettyPrintJson(content));
|
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;
|
break;
|
||||||
case HttpStatus.BAD_REQUEST_400:
|
case HttpStatus.BAD_REQUEST_400:
|
||||||
throw new UniFiInvalidCredentialsException("Invalid Credentials");
|
throw new UniFiInvalidCredentialsException("Invalid Credentials");
|
||||||
|
@ -184,6 +204,10 @@ public class UniFiControllerRequest<T> {
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getCsrfToken() {
|
||||||
|
return csrfToken;
|
||||||
|
}
|
||||||
|
|
||||||
private Request newRequest() {
|
private Request newRequest() {
|
||||||
HttpMethod method = bodyParameters.isEmpty() ? HttpMethod.GET : HttpMethod.POST;
|
HttpMethod method = bodyParameters.isEmpty() ? HttpMethod.GET : HttpMethod.POST;
|
||||||
HttpURI uri = new HttpURI(HttpScheme.HTTPS.asString(), host, port, path);
|
HttpURI uri = new HttpURI(HttpScheme.HTTPS.asString(), host, port, path);
|
||||||
|
@ -198,6 +222,10 @@ public class UniFiControllerRequest<T> {
|
||||||
StandardCharsets.UTF_8);
|
StandardCharsets.UTF_8);
|
||||||
request = request.content(content);
|
request = request.content(content);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!csrfToken.isEmpty())
|
||||||
|
request.header("x-csrf-token", this.csrfToken);
|
||||||
|
|
||||||
return request;
|
return request;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -88,7 +88,7 @@ public class UniFiControllerThingHandler extends BaseBridgeHandler {
|
||||||
logger.debug("Initializing the UniFi Controller Handler with config = {}", config);
|
logger.debug("Initializing the UniFi Controller Handler with config = {}", config);
|
||||||
try {
|
try {
|
||||||
controller = new UniFiController(httpClient, config.getHost(), config.getPort(), config.getUsername(),
|
controller = new UniFiController(httpClient, config.getHost(), config.getPort(), config.getUsername(),
|
||||||
config.getPassword());
|
config.getPassword(), config.isUniFiOS());
|
||||||
controller.start();
|
controller.start();
|
||||||
updateStatus(ONLINE);
|
updateStatus(ONLINE);
|
||||||
} catch (UniFiInvalidHostException e) {
|
} catch (UniFiInvalidHostException e) {
|
||||||
|
|
|
@ -21,6 +21,10 @@
|
||||||
<description>Port of the UniFi Controller</description>
|
<description>Port of the UniFi Controller</description>
|
||||||
<default>8443</default>
|
<default>8443</default>
|
||||||
</parameter>
|
</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">
|
<parameter name="username" type="text" required="true">
|
||||||
<label>Username</label>
|
<label>Username</label>
|
||||||
<description>The username to access the UniFi Controller.</description>
|
<description>The username to access the UniFi Controller.</description>
|
||||||
|
|
Loading…
Reference in New Issue