mirror of
https://github.com/danieldemus/openhab-addons
synced 2026-07-31 05:24:24 +02:00
[unifi] Add network thing (#18335)
Signed-off-by: Thomas Lauterbach <thomas@pop-os.amfthome.org>
This commit is contained in:
@@ -11,6 +11,7 @@ This binding integrates with [Ubiquiti UniFi Networks](https://www.ubnt.com/prod
|
||||
- `wiredClient` - A wired client connected to the UniFi network
|
||||
- `poePort` - A PoE (Power over Ethernet) port on a UniFi switch
|
||||
- `accessPoint` - An access point managed by the UniFi controller software
|
||||
- `network` - A network managed by the UniFi controller software.
|
||||
|
||||
## Discovery
|
||||
|
||||
@@ -114,6 +115,14 @@ The following table describes the `accessPoint` configuration parameters:
|
||||
| mac | The MAC address of the access point | Required | - |
|
||||
| site | The site where the access point should be found | Optional | - |
|
||||
|
||||
### `network`
|
||||
|
||||
The following table describes the `network` configuration parameters:
|
||||
|
||||
| Parameter | Description | Config | Default |
|
||||
| ------------ | -------------------------------------------------------------|--------- | ------- |
|
||||
| nid | The id of the network | Required | - |
|
||||
|
||||
## Channels
|
||||
|
||||
### `site`
|
||||
@@ -252,6 +261,17 @@ The `accessPoint` information that is retrieved is available as these channels:
|
||||
| experience | Number:Dimensionless | The average health indication of the connected clients | Read |
|
||||
| led | Switch | Switch the LED on or off | Read, Write |
|
||||
|
||||
### `network`
|
||||
|
||||
The `network` information that is retrieved is available as these channels:
|
||||
|
||||
| Channel ID | Item Type | Description | Permissions |
|
||||
|-----------------|-----------|---------------------------------------------------------------------------------|-------------|
|
||||
| enable | Switch | Enable status of the network | Read, Write |
|
||||
| totalClients | Number | Total number of clients connected | Read |
|
||||
| site | String | UniFi Site the client is associated with | Read |
|
||||
| purpose | String | Purpose of the network (e.g. Corporate, Guest, WAN, VPN, VLAN Only) | Read |
|
||||
|
||||
## 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.
|
||||
|
||||
+8
-2
@@ -34,16 +34,18 @@ public final class UniFiBindingConstants {
|
||||
// List of all Thing Types
|
||||
public static final ThingTypeUID THING_TYPE_CONTROLLER = new ThingTypeUID(BINDING_ID, "controller");
|
||||
public static final ThingTypeUID THING_TYPE_SITE = new ThingTypeUID(BINDING_ID, "site");
|
||||
public static final ThingTypeUID THING_TYPE_NETWORK = new ThingTypeUID(BINDING_ID, "network");
|
||||
public static final ThingTypeUID THING_TYPE_WLAN = new ThingTypeUID(BINDING_ID, "wlan");
|
||||
public static final ThingTypeUID THING_TYPE_WIRED_CLIENT = new ThingTypeUID(BINDING_ID, "wiredClient");
|
||||
public static final ThingTypeUID THING_TYPE_WIRELESS_CLIENT = new ThingTypeUID(BINDING_ID, "wirelessClient");
|
||||
public static final ThingTypeUID THING_TYPE_POE_PORT = new ThingTypeUID(BINDING_ID, "poePort");
|
||||
public static final ThingTypeUID THING_TYPE_ACCESS_POINT = new ThingTypeUID(BINDING_ID, "accessPoint");
|
||||
public static final Set<ThingTypeUID> ALL_THING_TYPE_SUPPORTED = Set.of(THING_TYPE_CONTROLLER, THING_TYPE_SITE,
|
||||
THING_TYPE_NETWORK, THING_TYPE_WLAN, THING_TYPE_WIRED_CLIENT, THING_TYPE_WIRELESS_CLIENT,
|
||||
THING_TYPE_POE_PORT, THING_TYPE_ACCESS_POINT);
|
||||
public static final Set<ThingTypeUID> THING_TYPE_SUPPORTED = Set.of(THING_TYPE_SITE, THING_TYPE_NETWORK,
|
||||
THING_TYPE_WLAN, THING_TYPE_WIRED_CLIENT, THING_TYPE_WIRELESS_CLIENT, THING_TYPE_POE_PORT,
|
||||
THING_TYPE_ACCESS_POINT);
|
||||
public static final Set<ThingTypeUID> THING_TYPE_SUPPORTED = Set.of(THING_TYPE_SITE, THING_TYPE_WLAN,
|
||||
THING_TYPE_WIRED_CLIENT, THING_TYPE_WIRELESS_CLIENT, THING_TYPE_POE_PORT, THING_TYPE_ACCESS_POINT);
|
||||
|
||||
// List of site channels
|
||||
public static final String CHANNEL_TOTAL_CLIENTS = "totalClients";
|
||||
@@ -53,6 +55,9 @@ public final class UniFiBindingConstants {
|
||||
public static final String CHANNEL_GUEST_VOUCHER = "guestVoucher";
|
||||
public static final String CHANNEL_GUEST_VOUCHERS_GENERATE = "guestVouchersGenerate";
|
||||
|
||||
// List of network channels
|
||||
public static final String CHANNEL_PURPOSE = "purpose";
|
||||
|
||||
// List of wlan channels
|
||||
public static final String CHANNEL_SECURITY = "security";
|
||||
public static final String CHANNEL_WLANBAND = "wlanBand";
|
||||
@@ -112,6 +117,7 @@ public final class UniFiBindingConstants {
|
||||
public static final String PARAMETER_CID = "cid";
|
||||
public static final String PARAMETER_SID = "sid";
|
||||
public static final String PARAMETER_WID = "wid";
|
||||
public static final String PARAMETER_NID = "nid";
|
||||
public static final String PARAMETER_VOUCHER_COUNT = "voucherCount";
|
||||
public static final String PARAMETER_VOUCHER_EXPIRATION = "voucherExpiration";
|
||||
public static final String PARAMETER_VOUCHER_USERS = "voucherUsers";
|
||||
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2025 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;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.unifi.internal.handler.UniFiNetworkThingHandler;
|
||||
|
||||
/**
|
||||
* The {@link UniFiNetworkThingConfig} encapsulates all the configuration options for an instance of the
|
||||
* {@link UniFiNetworkThingHandler}.
|
||||
*
|
||||
* @author Thomas Lauterbach - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
@SuppressWarnings("unused")
|
||||
public class UniFiNetworkThingConfig {
|
||||
|
||||
private String nid = "";
|
||||
|
||||
public String getNetworkId() {
|
||||
return nid;
|
||||
}
|
||||
|
||||
private void setNetworkId(final String nid) {
|
||||
// method to avoid auto format mark the field as final
|
||||
this.nid = nid;
|
||||
}
|
||||
|
||||
public boolean isValid() {
|
||||
return !nid.isBlank();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("UniFiNetworkThingConfig{nid: '%s'}", nid);
|
||||
}
|
||||
}
|
||||
+3
@@ -21,6 +21,7 @@ import org.eclipse.jetty.util.ssl.SslContextFactory;
|
||||
import org.openhab.binding.unifi.internal.handler.UniFiAccessPointThingHandler;
|
||||
import org.openhab.binding.unifi.internal.handler.UniFiClientThingHandler;
|
||||
import org.openhab.binding.unifi.internal.handler.UniFiControllerThingHandler;
|
||||
import org.openhab.binding.unifi.internal.handler.UniFiNetworkThingHandler;
|
||||
import org.openhab.binding.unifi.internal.handler.UniFiPoePortThingHandler;
|
||||
import org.openhab.binding.unifi.internal.handler.UniFiSiteThingHandler;
|
||||
import org.openhab.binding.unifi.internal.handler.UniFiWlanThingHandler;
|
||||
@@ -82,6 +83,8 @@ public class UniFiThingHandlerFactory extends BaseThingHandlerFactory {
|
||||
return new UniFiControllerThingHandler((Bridge) thing, httpClient);
|
||||
} else if (THING_TYPE_SITE.equals(thingTypeUID)) {
|
||||
return new UniFiSiteThingHandler(thing);
|
||||
} else if (THING_TYPE_NETWORK.equals(thingTypeUID)) {
|
||||
return new UniFiNetworkThingHandler(thing);
|
||||
} else if (THING_TYPE_WLAN.equals(thingTypeUID)) {
|
||||
return new UniFiWlanThingHandler(thing);
|
||||
} else if (THING_TYPE_WIRELESS_CLIENT.equals(thingTypeUID) || THING_TYPE_WIRED_CLIENT.equals(thingTypeUID)) {
|
||||
|
||||
+28
-1
@@ -14,6 +14,7 @@ package org.openhab.binding.unifi.internal.api;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
@@ -23,6 +24,7 @@ import org.openhab.binding.unifi.internal.api.cache.UniFiControllerCache;
|
||||
import org.openhab.binding.unifi.internal.api.dto.UnfiPortOverrideJsonObject;
|
||||
import org.openhab.binding.unifi.internal.api.dto.UniFiClient;
|
||||
import org.openhab.binding.unifi.internal.api.dto.UniFiDevice;
|
||||
import org.openhab.binding.unifi.internal.api.dto.UniFiNetwork;
|
||||
import org.openhab.binding.unifi.internal.api.dto.UniFiSite;
|
||||
import org.openhab.binding.unifi.internal.api.dto.UniFiSwitchPorts;
|
||||
import org.openhab.binding.unifi.internal.api.dto.UniFiUnknownClient;
|
||||
@@ -34,6 +36,7 @@ import org.openhab.binding.unifi.internal.api.util.UnfiPortOverrideJsonElementDe
|
||||
import org.openhab.binding.unifi.internal.api.util.UniFiClientDeserializer;
|
||||
import org.openhab.binding.unifi.internal.api.util.UniFiClientInstanceCreator;
|
||||
import org.openhab.binding.unifi.internal.api.util.UniFiDeviceInstanceCreator;
|
||||
import org.openhab.binding.unifi.internal.api.util.UniFiNetworkInstanceCreator;
|
||||
import org.openhab.binding.unifi.internal.api.util.UniFiSiteInstanceCreator;
|
||||
import org.openhab.binding.unifi.internal.api.util.UniFiVoucherInstanceCreator;
|
||||
import org.openhab.binding.unifi.internal.api.util.UniFiWlanInstanceCreator;
|
||||
@@ -87,12 +90,14 @@ public class UniFiController {
|
||||
this.timeoutSeconds = timeoutSeconds;
|
||||
this.csrfToken = "";
|
||||
final UniFiSiteInstanceCreator siteInstanceCreator = new UniFiSiteInstanceCreator(cache);
|
||||
final UniFiNetworkInstanceCreator networkInstanceCreator = new UniFiNetworkInstanceCreator(cache);
|
||||
final UniFiWlanInstanceCreator wlanInstanceCreator = new UniFiWlanInstanceCreator(cache);
|
||||
final UniFiDeviceInstanceCreator deviceInstanceCreator = new UniFiDeviceInstanceCreator(cache);
|
||||
final UniFiClientInstanceCreator clientInstanceCreator = new UniFiClientInstanceCreator(cache);
|
||||
final UniFiVoucherInstanceCreator voucherInstanceCreator = new UniFiVoucherInstanceCreator(cache);
|
||||
this.gson = new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)
|
||||
.registerTypeAdapter(UniFiSite.class, siteInstanceCreator)
|
||||
.registerTypeAdapter(UniFiNetwork.class, networkInstanceCreator)
|
||||
.registerTypeAdapter(UniFiWlan.class, wlanInstanceCreator)
|
||||
.registerTypeAdapter(UniFiDevice.class, deviceInstanceCreator)
|
||||
.registerTypeAdapter(UniFiClient.class, new UniFiClientDeserializer())
|
||||
@@ -149,6 +154,7 @@ public class UniFiController {
|
||||
synchronized (this) {
|
||||
cache.clear();
|
||||
final Collection<UniFiSite> sites = refreshSites();
|
||||
refreshNetworks(sites);
|
||||
refreshWlans(sites);
|
||||
refreshDevices(sites);
|
||||
refreshClients(sites);
|
||||
@@ -208,8 +214,17 @@ public class UniFiController {
|
||||
refresh();
|
||||
}
|
||||
|
||||
public void enableNetwork(final UniFiNetwork network, final boolean enable) throws UniFiException {
|
||||
final UniFiControllerRequest<Void> req = newRequest(Void.class, HttpMethod.PUT, gson);
|
||||
req.setAPIPath(String.format("/api/s/%s/group/networkconf", network.getSite().getName()));
|
||||
req.setBodyParameter("data", Map.of("enabled", enable));
|
||||
req.setBodyParameter("id", new String[] { network.getId() });
|
||||
executeRequest(req);
|
||||
refresh();
|
||||
}
|
||||
|
||||
public void enableWifi(final UniFiWlan wlan, final boolean enable) throws UniFiException {
|
||||
final UniFiControllerRequest<Void> req = newRequest(Void.class, HttpMethod.PUT, poeGson);
|
||||
final UniFiControllerRequest<Void> req = newRequest(Void.class, HttpMethod.PUT, gson);
|
||||
req.setAPIPath(String.format("/api/s/%s/rest/wlanconf/%s", wlan.getSite().getName(), wlan.getId()));
|
||||
req.setBodyParameter("_id", wlan.getId());
|
||||
req.setBodyParameter("enabled", enable ? "true" : "false");
|
||||
@@ -309,6 +324,18 @@ public class UniFiController {
|
||||
return cache.setSites(executeRequest(req));
|
||||
}
|
||||
|
||||
private void refreshNetworks(final Collection<UniFiSite> sites) throws UniFiException {
|
||||
for (final UniFiSite site : sites) {
|
||||
cache.putNetworks(getNetworks(site));
|
||||
}
|
||||
}
|
||||
|
||||
private UniFiNetwork @Nullable [] getNetworks(final UniFiSite site) throws UniFiException {
|
||||
final UniFiControllerRequest<UniFiNetwork[]> req = newRequest(UniFiNetwork[].class, HttpMethod.GET, gson);
|
||||
req.setAPIPath(String.format("/api/s/%s/rest/networkconf", site.getName()));
|
||||
return executeRequest(req);
|
||||
}
|
||||
|
||||
private void refreshWlans(final Collection<UniFiSite> sites) throws UniFiException {
|
||||
for (final UniFiSite site : sites) {
|
||||
cache.putWlans(getWlans(site));
|
||||
|
||||
+17
@@ -25,6 +25,7 @@ import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.unifi.internal.api.dto.UniFiClient;
|
||||
import org.openhab.binding.unifi.internal.api.dto.UniFiDevice;
|
||||
import org.openhab.binding.unifi.internal.api.dto.UniFiNetwork;
|
||||
import org.openhab.binding.unifi.internal.api.dto.UniFiPortTuple;
|
||||
import org.openhab.binding.unifi.internal.api.dto.UniFiSite;
|
||||
import org.openhab.binding.unifi.internal.api.dto.UniFiSwitchPorts;
|
||||
@@ -46,6 +47,7 @@ public class UniFiControllerCache {
|
||||
private final Logger logger = LoggerFactory.getLogger(UniFiControllerCache.class);
|
||||
|
||||
private final UniFiSiteCache sitesCache = new UniFiSiteCache();
|
||||
private final UniFiNetworkCache networksCache = new UniFiNetworkCache();
|
||||
private final UniFiWlanCache wlansCache = new UniFiWlanCache();
|
||||
private final UniFiDeviceCache devicesCache = new UniFiDeviceCache();
|
||||
private final UniFiClientCache clientsCache = new UniFiClientCache();
|
||||
@@ -55,6 +57,7 @@ public class UniFiControllerCache {
|
||||
|
||||
public void clear() {
|
||||
sitesCache.clear();
|
||||
networksCache.clear();
|
||||
wlansCache.clear();
|
||||
devicesCache.clear();
|
||||
clientsCache.clear();
|
||||
@@ -77,6 +80,20 @@ public class UniFiControllerCache {
|
||||
return sitesCache.values();
|
||||
}
|
||||
|
||||
// Networks Cache
|
||||
|
||||
public void putNetworks(final UniFiNetwork @Nullable [] networks) {
|
||||
networksCache.putAll(networks);
|
||||
}
|
||||
|
||||
public @Nullable UniFiNetwork getNetwork(@Nullable final String id) {
|
||||
return networksCache.get(id);
|
||||
}
|
||||
|
||||
public Collection<UniFiNetwork> getNetworks() {
|
||||
return networksCache.values();
|
||||
}
|
||||
|
||||
// Wlans Cache
|
||||
|
||||
public void putWlans(final UniFiWlan @Nullable [] wlans) {
|
||||
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2025 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.api.cache;
|
||||
|
||||
import static org.openhab.binding.unifi.internal.api.cache.UniFiCache.Prefix.ID;
|
||||
import static org.openhab.binding.unifi.internal.api.cache.UniFiCache.Prefix.NAME;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.unifi.internal.api.dto.UniFiNetwork;
|
||||
|
||||
/**
|
||||
* The {@link UniFiNetworkCache} is a specific implementation of {@link UniFiCache} for the purpose of caching
|
||||
* {@link UniFiNetwork} instances.
|
||||
*
|
||||
* The cache uses the following prefixes: <code>id</code>, <code>name</code>
|
||||
*
|
||||
* @author Thomas Lauterbach - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
class UniFiNetworkCache extends UniFiCache<UniFiNetwork> {
|
||||
|
||||
public UniFiNetworkCache() {
|
||||
super(ID, NAME);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @Nullable String getSuffix(final UniFiNetwork network, final Prefix prefix) {
|
||||
switch (prefix) {
|
||||
case ID:
|
||||
return network.getId();
|
||||
case NAME:
|
||||
return network.getName();
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
+6
@@ -61,6 +61,8 @@ public abstract class UniFiClient implements HasId {
|
||||
@SerializedName("satisfaction")
|
||||
private Integer experience;
|
||||
|
||||
private String networkId;
|
||||
|
||||
protected UniFiClient(final UniFiControllerCache cache) {
|
||||
this.cache = cache;
|
||||
}
|
||||
@@ -122,6 +124,10 @@ public abstract class UniFiClient implements HasId {
|
||||
return experience;
|
||||
}
|
||||
|
||||
public UniFiNetwork getNetwork() {
|
||||
return cache.getNetwork(networkId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format(
|
||||
|
||||
+66
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2025 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.api.dto;
|
||||
|
||||
import org.openhab.binding.unifi.internal.api.cache.UniFiControllerCache;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* @author Thomas Lauterbach - Initial contribution
|
||||
*/
|
||||
public class UniFiNetwork implements HasId {
|
||||
|
||||
protected final transient UniFiControllerCache cache;
|
||||
|
||||
@SerializedName("_id")
|
||||
private String id;
|
||||
|
||||
private String name;
|
||||
|
||||
private String siteId;
|
||||
|
||||
private boolean enabled;
|
||||
|
||||
private String purpose;
|
||||
|
||||
public UniFiNetwork(final UniFiControllerCache cache) {
|
||||
this.cache = cache;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public UniFiSite getSite() {
|
||||
return cache.getSite(siteId);
|
||||
}
|
||||
|
||||
public boolean isEnabled() {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
public String getPurpose() {
|
||||
return purpose;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("UniFiNetwork{id: '%s', name: '%s'}", id, name);
|
||||
}
|
||||
}
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2025 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.api.util;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.unifi.internal.api.cache.UniFiControllerCache;
|
||||
import org.openhab.binding.unifi.internal.api.dto.UniFiNetwork;
|
||||
|
||||
import com.google.gson.InstanceCreator;
|
||||
import com.google.gson.JsonSyntaxException;
|
||||
|
||||
/**
|
||||
* The {@link UniFiNetworkInstanceCreator} creates instances of {@link UniFiNetwork}s during the JSON unmarshalling of
|
||||
* controller responses.
|
||||
*
|
||||
* @author Thomas Lauterbach - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class UniFiNetworkInstanceCreator implements InstanceCreator<UniFiNetwork> {
|
||||
|
||||
private final UniFiControllerCache cache;
|
||||
|
||||
public UniFiNetworkInstanceCreator(final UniFiControllerCache cache) {
|
||||
this.cache = cache;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UniFiNetwork createInstance(final @Nullable Type type) {
|
||||
if (UniFiNetwork.class.equals(type)) {
|
||||
return new UniFiNetwork(cache);
|
||||
} else {
|
||||
throw new JsonSyntaxException("Expected a UniFiNetwork type, but got " + type);
|
||||
}
|
||||
}
|
||||
}
|
||||
+119
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2025 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.handler;
|
||||
|
||||
import static org.openhab.binding.unifi.internal.UniFiBindingConstants.*;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.unifi.internal.UniFiNetworkThingConfig;
|
||||
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;
|
||||
import org.openhab.binding.unifi.internal.api.dto.UniFiClient;
|
||||
import org.openhab.binding.unifi.internal.api.dto.UniFiNetwork;
|
||||
import org.openhab.binding.unifi.internal.api.dto.UniFiSite;
|
||||
import org.openhab.core.library.types.DecimalType;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
import org.openhab.core.library.types.StringType;
|
||||
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.types.Command;
|
||||
import org.openhab.core.types.State;
|
||||
import org.openhab.core.types.UnDefType;
|
||||
|
||||
/**
|
||||
* The {@link UniFiNetworkThingHandler} is responsible for handling commands and status updates for a wireless network.
|
||||
*
|
||||
* @author Thomas Lauterbach - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class UniFiNetworkThingHandler extends UniFiBaseThingHandler<UniFiNetwork, UniFiNetworkThingConfig> {
|
||||
|
||||
private UniFiNetworkThingConfig config = new UniFiNetworkThingConfig();
|
||||
|
||||
public UniFiNetworkThingHandler(final Thing thing) {
|
||||
super(thing);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean initialize(final UniFiNetworkThingConfig config) {
|
||||
this.config = config;
|
||||
|
||||
if (!config.isValid()) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
|
||||
"@text/error.thing.network.offline.configuration_error");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @Nullable UniFiNetwork getEntity(final UniFiControllerCache cache) {
|
||||
return cache.getNetwork(config.getNetworkId());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected State getChannelState(final UniFiNetwork network, final String channelId) {
|
||||
final State state;
|
||||
|
||||
switch (channelId) {
|
||||
case CHANNEL_ENABLE:
|
||||
state = OnOffType.from(network.isEnabled());
|
||||
break;
|
||||
case CHANNEL_SITE:
|
||||
final UniFiSite site = network.getSite();
|
||||
if (site != null && site.getDescription() != null && !site.getDescription().isBlank()) {
|
||||
state = StringType.valueOf(site.getDescription());
|
||||
} else {
|
||||
state = UnDefType.UNDEF;
|
||||
}
|
||||
break;
|
||||
case CHANNEL_PURPOSE:
|
||||
state = StringType.valueOf(network.getPurpose());
|
||||
break;
|
||||
case CHANNEL_TOTAL_CLIENTS:
|
||||
state = countClients(network);
|
||||
break;
|
||||
default:
|
||||
// Unsupported channel; nothing to update
|
||||
state = UnDefType.NULL;
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
private static State countClients(final UniFiNetwork network) {
|
||||
final UniFiSite site = network.getSite();
|
||||
|
||||
if (site == null) {
|
||||
return UnDefType.UNDEF;
|
||||
} else {
|
||||
return new DecimalType(site.getCache().countClients(site, c -> c instanceof UniFiClient client
|
||||
&& (network.getName() != null && network.equals(client.getNetwork()))));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean handleCommand(final UniFiController controller, final UniFiNetwork network,
|
||||
final ChannelUID channelUID, Command command) throws UniFiException {
|
||||
final String channelID = channelUID.getId();
|
||||
|
||||
if (CHANNEL_ENABLE.equals(channelID) && command instanceof OnOffType && network.getSite() != null) {
|
||||
controller.enableNetwork(network, OnOffType.ON == command);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
+16
@@ -15,6 +15,7 @@ package org.openhab.binding.unifi.internal.handler;
|
||||
import static org.openhab.binding.unifi.internal.UniFiBindingConstants.DEVICE_TYPE_UAP;
|
||||
import static org.openhab.binding.unifi.internal.UniFiBindingConstants.PARAMETER_CID;
|
||||
import static org.openhab.binding.unifi.internal.UniFiBindingConstants.PARAMETER_MAC_ADDRESS;
|
||||
import static org.openhab.binding.unifi.internal.UniFiBindingConstants.PARAMETER_NID;
|
||||
import static org.openhab.binding.unifi.internal.UniFiBindingConstants.PARAMETER_PORT_NUMBER;
|
||||
import static org.openhab.binding.unifi.internal.UniFiBindingConstants.PARAMETER_SID;
|
||||
import static org.openhab.binding.unifi.internal.UniFiBindingConstants.PARAMETER_SITE;
|
||||
@@ -32,6 +33,7 @@ import org.openhab.binding.unifi.internal.api.UniFiException;
|
||||
import org.openhab.binding.unifi.internal.api.cache.UniFiControllerCache;
|
||||
import org.openhab.binding.unifi.internal.api.dto.UniFiClient;
|
||||
import org.openhab.binding.unifi.internal.api.dto.UniFiDevice;
|
||||
import org.openhab.binding.unifi.internal.api.dto.UniFiNetwork;
|
||||
import org.openhab.binding.unifi.internal.api.dto.UniFiPortTuple;
|
||||
import org.openhab.binding.unifi.internal.api.dto.UniFiSite;
|
||||
import org.openhab.binding.unifi.internal.api.dto.UniFiSwitchPorts;
|
||||
@@ -81,6 +83,7 @@ public class UniFiThingDiscoveryService extends AbstractThingHandlerDiscoverySer
|
||||
final ThingUID bridgeUID = thingHandler.getThing().getUID();
|
||||
|
||||
discoverSites(cache, bridgeUID);
|
||||
discoverNetworks(cache, bridgeUID);
|
||||
discoverWlans(cache, bridgeUID);
|
||||
discoverClients(cache, bridgeUID);
|
||||
discoverPoePorts(cache, bridgeUID);
|
||||
@@ -102,6 +105,19 @@ public class UniFiThingDiscoveryService extends AbstractThingHandlerDiscoverySer
|
||||
}
|
||||
}
|
||||
|
||||
private void discoverNetworks(final UniFiControllerCache cache, final ThingUID bridgeUID) {
|
||||
for (final UniFiNetwork network : cache.getNetworks()) {
|
||||
final ThingUID thingUID = new ThingUID(UniFiBindingConstants.THING_TYPE_NETWORK, bridgeUID,
|
||||
stripIdShort(network.getId()));
|
||||
final Map<String, Object> properties = Map.of(PARAMETER_NID, network.getId());
|
||||
|
||||
thingDiscovered(
|
||||
DiscoveryResultBuilder.create(thingUID).withThingType(UniFiBindingConstants.THING_TYPE_NETWORK)
|
||||
.withBridge(bridgeUID).withRepresentationProperty(PARAMETER_NID).withTTL(TTL_SECONDS)
|
||||
.withProperties(properties).withLabel(network.getName()).build());
|
||||
}
|
||||
}
|
||||
|
||||
private void discoverWlans(final UniFiControllerCache cache, final ThingUID bridgeUID) {
|
||||
for (final UniFiWlan wlan : cache.getWlans()) {
|
||||
final ThingUID thingUID = new ThingUID(UniFiBindingConstants.THING_TYPE_WLAN, bridgeUID,
|
||||
|
||||
@@ -50,6 +50,13 @@
|
||||
</parameter>
|
||||
</config-description>
|
||||
|
||||
<config-description uri="thing-type:unifi:network">
|
||||
<parameter name="nid" type="text" required="true">
|
||||
<label>Network Id</label>
|
||||
<description>The id or name of the network</description>
|
||||
</parameter>
|
||||
</config-description>
|
||||
|
||||
<config-description uri="thing-type:unifi:wlan">
|
||||
<parameter name="wid" type="text" required="true">
|
||||
<label>WLAN Id</label>
|
||||
|
||||
@@ -17,6 +17,9 @@ thing-type.unifi.accessPoint.channel.online.description = Online status of the d
|
||||
thing-type.unifi.accessPoint.channel.uptime.description = Uptime of the device (in seconds)
|
||||
thing-type.unifi.controller.label = UniFi Controller
|
||||
thing-type.unifi.controller.description = A UniFi controller
|
||||
thing-type.unifi.network.label = UniFi Network
|
||||
thing-type.unifi.network.description = A UniFi Network
|
||||
thing-type.unifi.network.channel.site.description = UniFi Site the network is associated with
|
||||
thing-type.unifi.poePort.label = UniFi PoE Port
|
||||
thing-type.unifi.poePort.description = A Power Over Ethernet (PoE) port on a UniFi switch
|
||||
thing-type.unifi.site.label = UniFi Site
|
||||
@@ -54,6 +57,8 @@ thing-type.config.unifi.controller.unifios.label = UniFi OS
|
||||
thing-type.config.unifi.controller.unifios.description = If the UniFi Controller is running on UniFi OS.
|
||||
thing-type.config.unifi.controller.username.label = Username
|
||||
thing-type.config.unifi.controller.username.description = The username to access the UniFi Controller.
|
||||
thing-type.config.unifi.network.nid.label = Network Id
|
||||
thing-type.config.unifi.network.nid.description = The id or name of the network
|
||||
thing-type.config.unifi.poePort.macAddress.label = Switch MAC Address
|
||||
thing-type.config.unifi.poePort.macAddress.description = The MAC address of the switch this port is part of
|
||||
thing-type.config.unifi.poePort.portNumber.label = Port Number
|
||||
@@ -106,6 +111,8 @@ channel-type.unifi.macAddress.label = MAC Address
|
||||
channel-type.unifi.macAddress.description = MAC address of the client
|
||||
channel-type.unifi.name.label = Name
|
||||
channel-type.unifi.name.description = Name of the client
|
||||
channel-type.unifi.networkEnable.label = Enable
|
||||
channel-type.unifi.networkEnable.description = Enable status of the network
|
||||
channel-type.unifi.online.label = Online
|
||||
channel-type.unifi.online.description = Online status of the client
|
||||
channel-type.unifi.passphrase.label = Passphrase
|
||||
@@ -129,6 +136,13 @@ channel-type.unifi.poeVoltage.label = Port PoE Voltage
|
||||
channel-type.unifi.poeVoltage.description = Voltage usage of the PoE port
|
||||
channel-type.unifi.portOnline.label = Port Active
|
||||
channel-type.unifi.portOnline.description = PoE port is active
|
||||
channel-type.unifi.purpose.label = Purpose
|
||||
channel-type.unifi.purpose.description = Purpose of the network
|
||||
channel-type.unifi.purpose.state.option.corporate = Corporate
|
||||
channel-type.unifi.purpose.state.option.guest = Guest
|
||||
channel-type.unifi.purpose.state.option.remote-user-vpn = VPN
|
||||
channel-type.unifi.purpose.state.option.wan = WAN
|
||||
channel-type.unifi.purpose.state.option.vlan-only = VLAN Only
|
||||
channel-type.unifi.qrcodeEncoding.label = QR Code Encoding
|
||||
channel-type.unifi.qrcodeEncoding.description = MECARD like encoding to generate a QRCode for easy access to the Wi-Fi network
|
||||
channel-type.unifi.reconnect.label = Reconnect
|
||||
@@ -195,6 +209,7 @@ error.thing.poe.offline.configuration_error = The configuration parameter macAdd
|
||||
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.
|
||||
error.thing.ap.offline.configuration_error = The configuration parameter mac must be set and not be empty
|
||||
error.thing.network.offline.configuration_error = The configuration parameter networkId must be set and not be empty
|
||||
|
||||
# actions
|
||||
|
||||
|
||||
@@ -34,6 +34,27 @@
|
||||
<config-description-ref uri="thing-type:unifi:site"/>
|
||||
</thing-type>
|
||||
|
||||
<thing-type id="network">
|
||||
<supported-bridge-type-refs>
|
||||
<bridge-type-ref id="controller"/>
|
||||
</supported-bridge-type-refs>
|
||||
|
||||
<label>UniFi Network</label>
|
||||
<description>A UniFi Network</description>
|
||||
|
||||
<channels>
|
||||
<channel id="enable" typeId="networkEnable"/>
|
||||
<channel id="totalClients" typeId="totalClients"/>
|
||||
<channel id="site" typeId="site">
|
||||
<description>UniFi Site the network is associated with</description>
|
||||
</channel>
|
||||
<channel id="purpose" typeId="purpose"/>
|
||||
</channels>
|
||||
<representation-property>nid</representation-property>
|
||||
|
||||
<config-description-ref uri="thing-type:unifi:network"/>
|
||||
</thing-type>
|
||||
|
||||
<thing-type id="wlan">
|
||||
<supported-bridge-type-refs>
|
||||
<bridge-type-ref id="controller"/>
|
||||
@@ -491,4 +512,25 @@
|
||||
</state>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="purpose">
|
||||
<item-type>String</item-type>
|
||||
<label>Purpose</label>
|
||||
<description>Purpose of the network</description>
|
||||
<state readOnly="true">
|
||||
<options>
|
||||
<option value="corporate">Corporate</option>
|
||||
<option value="guest">Guest</option>
|
||||
<option value="remote-user-vpn">VPN</option>
|
||||
<option value="wan">WAN</option>
|
||||
<option value="vlan-only">VLAN Only</option>
|
||||
</options>
|
||||
</state>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="networkEnable">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Enable</label>
|
||||
<description>Enable status of the network</description>
|
||||
</channel-type>
|
||||
|
||||
</thing:thing-descriptions>
|
||||
|
||||
Reference in New Issue
Block a user