]> git.basschouten.com Git - openhab-addons.git/commitdiff
[unifi] Add support for new thing type access point (#17499)
authorThomas Lauterbach <2452988+DrRSatzteil@users.noreply.github.com>
Fri, 4 Oct 2024 15:47:28 +0000 (17:47 +0200)
committerGitHub <noreply@github.com>
Fri, 4 Oct 2024 15:47:28 +0000 (17:47 +0200)
Signed-off-by: Thomas Lauterbach <thomas_lauterbach@arcor.de>
12 files changed:
bundles/org.openhab.binding.unifi/README.md
bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/UniFiAccessPointThingConfig.java [new file with mode: 0644]
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/UniFiThingHandlerFactory.java
bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/UniFiController.java
bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/cache/UniFiControllerCache.java
bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/dto/UniFiDevice.java
bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/handler/UniFiAccessPointThingHandler.java [new file with mode: 0644]
bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/handler/UniFiThingDiscoveryService.java
bundles/org.openhab.binding.unifi/src/main/resources/OH-INF/config/config.xml
bundles/org.openhab.binding.unifi/src/main/resources/OH-INF/i18n/unifi.properties
bundles/org.openhab.binding.unifi/src/main/resources/OH-INF/thing/thing-types.xml

index 449f4432aee0bba17752a528bf63d45a44c328fe..712d5489d2380c4dc0c144ab74f23678db7d05f1 100644 (file)
@@ -10,6 +10,7 @@ This binding integrates with [Ubiquiti UniFi Networks](https://www.ubnt.com/prod
 - `wirelessClient` - Any wireless client connected to a UniFi wireless network
 - `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
 
 ## Discovery
 
@@ -103,6 +104,15 @@ The following table describes the `poePort` configuration parameters:
 | portNumber | The port number as reported by the switch (starts with 1) | Required |
 | macAddress | The MAC address of the switch device the port is part of  | Required |
 
+### `accessPoint`
+
+The following table describes the `accessPoint` configuration parameters:
+
+| Parameter    | Description                                     | Config   | Default |
+| ------------ | ------------------------------------------------|--------- | ------- |
+| mac          | The MAC address of the access point             | Required | -       |
+| site         | The site where the access point should be found | Optional | -       |
+
 ## Channels
 
 ### `site`
@@ -225,6 +235,14 @@ The `poePort` information that is retrieved is available as these channels:
 The `enable` switch channel has a configuration parameter `mode` which is the value used to switch PoE on when the channel is switched to ON.
 The default mode value is `auto`.
 
+### `accessPoint`
+
+The `accessPoint` information that is retrieved is available as these channels:
+
+| Channel ID | Item Type | Description                        | Permissions |
+|------------|-----------|------------------------------------|-------------|
+| enable     | Switch    | Enable or disable the access point | Read, Write |
+
 ## 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.
diff --git a/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/UniFiAccessPointThingConfig.java b/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/UniFiAccessPointThingConfig.java
new file mode 100644 (file)
index 0000000..e47e307
--- /dev/null
@@ -0,0 +1,52 @@
+/**
+ * Copyright (c) 2010-2024 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;
+
+/**
+ * The {@link UniFiAccessPointThingConfig} encapsulates all the configuration options for an instance of the
+ * {@link org.openhab.binding.unifi.internal.handler.UniFiAccessPointThingHandler}.
+ *
+ * @author Thomas Lauterbach - Initial contribution
+ */
+@NonNullByDefault
+@SuppressWarnings("unused")
+public class UniFiAccessPointThingConfig {
+
+    private String macAddress = "";
+
+    private String site = "";
+
+    public String getSite() {
+        return site;
+    }
+
+    private void setSite(final String site) {
+        // method to avoid ide auto format mark the field as final
+        this.site = site;
+    }
+
+    public String getMacAddress() {
+        return macAddress;
+    }
+
+    private void setMacAddress(final String macAddress) {
+        // method to avoid ide auto format mark the field as final
+        this.macAddress = macAddress;
+    }
+
+    public boolean isValid() {
+        return !macAddress.isBlank();
+    }
+}
index 6b9155698849d7c2685ee80d6b0a8473ad5e0d94..189b6a57de3705f24cdd661cd9414e1283aa907c 100644 (file)
@@ -38,10 +38,12 @@ public final class UniFiBindingConstants {
     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_WLAN, THING_TYPE_WIRED_CLIENT, THING_TYPE_WIRELESS_CLIENT, THING_TYPE_POE_PORT);
+            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_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";
@@ -93,6 +95,9 @@ public final class UniFiBindingConstants {
     public static final String CHANNEL_PORT_POE_VOLTAGE = "voltage";
     public static final String CHANNEL_PORT_POE_CURRENT = "current";
 
+    // List of access point channels
+    public static final String CHANNEL_AP_ENABLE = "enable";
+
     // List of all Parameters
     public static final String PARAMETER_HOST = "host";
     public static final String PARAMETER_PORT = "port";
@@ -113,6 +118,9 @@ public final class UniFiBindingConstants {
     public static final String PARAMETER_MAC_ADDRESS = "macAddress";
     public static final String PARAMETER_WIFI_NAME = "wifi";
 
+    // UniFi device types
+    public static final String DEVICE_TYPE_UAP = "uap";
+
     private UniFiBindingConstants() {
         // Constants class
     }
index f8bc1cfdc890c279d7fe9a0116056e6f095c0653..480612e5d4450c4b0097560e2f03555c5770c4d7 100644 (file)
@@ -18,6 +18,7 @@ import org.eclipse.jdt.annotation.NonNullByDefault;
 import org.eclipse.jdt.annotation.Nullable;
 import org.eclipse.jetty.client.HttpClient;
 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.UniFiPoePortThingHandler;
@@ -87,6 +88,8 @@ public class UniFiThingHandlerFactory extends BaseThingHandlerFactory {
             return new UniFiClientThingHandler(thing);
         } else if (THING_TYPE_POE_PORT.equals(thingTypeUID)) {
             return new UniFiPoePortThingHandler(thing);
+        } else if (THING_TYPE_ACCESS_POINT.equals(thingTypeUID)) {
+            return new UniFiAccessPointThingHandler(thing);
         }
         return null;
     }
index 05b7c69d962a4a8a59254f2c99b7f3b6296b35af..fa93d7bde8752060579fb856109f353fa0ea6dd9 100644 (file)
@@ -215,6 +215,15 @@ public class UniFiController {
         refresh();
     }
 
+    public void disableAccessPoint(final UniFiDevice device, final boolean disable) throws UniFiException {
+        final UniFiControllerRequest<Void> req = newRequest(Void.class, HttpMethod.PUT, gson);
+        req.setAPIPath(String.format("/api/s/%s/rest/device/%s", device.getSite().getName(), device.getId()));
+        req.setBodyParameter("_id", device.getId());
+        req.setBodyParameter("disabled", disable ? "true" : "false");
+        executeRequest(req);
+        refresh();
+    }
+
     public void generateVouchers(final UniFiSite site, final int count, final int expiration, final int users,
             @Nullable Integer upLimit, @Nullable Integer downLimit, @Nullable Integer dataQuota) throws UniFiException {
         final UniFiControllerRequest<Void> req = newRequest(Void.class, HttpMethod.POST, gson);
index 33e476689c5058e759fb3d43b46d06673cffb429..0d0e6c0a14b17bb54a8b1e2f3f955e69093ea80d 100644 (file)
@@ -124,6 +124,10 @@ public class UniFiControllerCache {
         return devicesCache.get(id);
     }
 
+    public Collection<UniFiDevice> getDevices() {
+        return devicesCache.values();
+    }
+
     public UniFiSwitchPorts getSwitchPorts(@Nullable final String deviceId) {
         return deviceId == null ? new UniFiSwitchPorts()
                 : devicesToPortTables.getOrDefault(deviceId, new UniFiSwitchPorts());
index 0b88d78a5970c69c410664da86b4752b180b4182..1ad6420ccce40dc0fcd504060375eeaeea969991 100644 (file)
@@ -38,6 +38,8 @@ public class UniFiDevice implements HasId {
 
     private String model;
 
+    private String type;
+
     private String name;
 
     private String siteId;
@@ -46,6 +48,8 @@ public class UniFiDevice implements HasId {
 
     private JsonObject[] portOverrides;
 
+    private boolean disabled;
+
     public UniFiDevice(final UniFiControllerCache cache) {
         this.cache = cache;
     }
@@ -55,6 +59,10 @@ public class UniFiDevice implements HasId {
         return id;
     }
 
+    public String getType() {
+        return type;
+    }
+
     public String getModel() {
         return model;
     }
@@ -79,8 +87,13 @@ public class UniFiDevice implements HasId {
         return portOverrides;
     }
 
+    public boolean isDisabled() {
+        return disabled;
+    }
+
     @Override
     public String toString() {
-        return String.format("UniFiDevice{mac: '%s', name: '%s', model: '%s', site: %s}", mac, name, model, getSite());
+        return String.format("UniFiDevice{mac: '%s', name: '%s', type: %s, model: '%s', disabled: %b, site: %s}", mac,
+                name, type, model, disabled, getSite());
     }
 }
diff --git a/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/handler/UniFiAccessPointThingHandler.java b/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/handler/UniFiAccessPointThingHandler.java
new file mode 100644 (file)
index 0000000..419a488
--- /dev/null
@@ -0,0 +1,112 @@
+/**
+ * Copyright (c) 2010-2024 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.CHANNEL_AP_ENABLE;
+import static org.openhab.binding.unifi.internal.UniFiBindingConstants.DEVICE_TYPE_UAP;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+import org.openhab.binding.unifi.internal.UniFiAccessPointThingConfig;
+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.UniFiDevice;
+import org.openhab.binding.unifi.internal.api.dto.UniFiSite;
+import org.openhab.core.library.types.OnOffType;
+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.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * An access point managed by the UniFi controller software.
+ *
+ * @author Thomas Lauterbach - Initial contribution
+ */
+@NonNullByDefault
+public class UniFiAccessPointThingHandler extends UniFiBaseThingHandler<UniFiDevice, UniFiAccessPointThingConfig> {
+
+    private final Logger logger = LoggerFactory.getLogger(UniFiAccessPointThingHandler.class);
+
+    private UniFiAccessPointThingConfig config = new UniFiAccessPointThingConfig();
+
+    public UniFiAccessPointThingHandler(final Thing thing) {
+        super(thing);
+    }
+
+    private static boolean belongsToSite(final UniFiDevice client, final String siteName) {
+        boolean result = true;
+        if (!siteName.isEmpty()) {
+            final UniFiSite site = client.getSite();
+            if (site == null || !site.matchesName(siteName)) {
+                result = false;
+            }
+        }
+        return result;
+    }
+
+    @Override
+    protected boolean initialize(final UniFiAccessPointThingConfig config) {
+        this.config = config;
+        if (!config.isValid()) {
+            updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
+                    "@text/error.thing.ap.offline.configuration_error");
+            return false;
+        }
+        return true;
+    }
+
+    @Override
+    protected @Nullable UniFiDevice getEntity(final UniFiControllerCache cache) {
+        final UniFiDevice device = cache.getDevice(config.getMacAddress());
+        if (device == null || !belongsToSite(device, config.getSite()) || !DEVICE_TYPE_UAP.equals(device.getType())) {
+            return null;
+        }
+        return device;
+    }
+
+    @Override
+    protected State getChannelState(final UniFiDevice device, final String channelId) {
+        State state = getDefaultState(channelId);
+
+        switch (channelId) {
+            case CHANNEL_AP_ENABLE:
+                state = OnOffType.from(!device.isDisabled());
+                break;
+        }
+        return state;
+    }
+
+    @Override
+    protected boolean handleCommand(final UniFiController controller, final UniFiDevice device,
+            final ChannelUID channelUID, final Command command) throws UniFiException {
+        final String channelID = channelUID.getIdWithoutGroup();
+
+        if (CHANNEL_AP_ENABLE.equals(channelID) && command instanceof OnOffType onOffCommand) {
+            return handleEnableCommand(controller, device, channelUID, onOffCommand);
+        }
+        return false;
+    }
+
+    private boolean handleEnableCommand(final UniFiController controller, final UniFiDevice device,
+            final ChannelUID channelUID, final OnOffType command) throws UniFiException {
+        controller.disableAccessPoint(device, command == OnOffType.OFF);
+        refresh();
+        return true;
+    }
+}
index 51cff7b9312964e5e33be3536e6f7414350e3bfd..a3d4a17966c50a067693f156ab6cee114e3b0a07 100644 (file)
@@ -12,6 +12,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_PORT_NUMBER;
@@ -31,6 +32,7 @@ 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.UniFiDevice;
 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;
@@ -83,6 +85,7 @@ public class UniFiThingDiscoveryService extends AbstractThingHandlerDiscoverySer
             discoverWlans(cache, bridgeUID);
             discoverClients(cache, bridgeUID);
             discoverPoePorts(cache, bridgeUID);
+            discoverAccessPoints(cache, bridgeUID);
         } catch (final UniFiException e) {
             logger.debug("Exception during discovery of UniFi Things", e);
         }
@@ -128,6 +131,20 @@ public class UniFiThingDiscoveryService extends AbstractThingHandlerDiscoverySer
         }
     }
 
+    private void discoverAccessPoints(final UniFiControllerCache cache, final ThingUID bridgeUID) {
+        for (final UniFiDevice ud : cache.getDevices()) {
+            if (DEVICE_TYPE_UAP.equals(ud.getType())) {
+                final var thingTypeUID = UniFiBindingConstants.THING_TYPE_ACCESS_POINT;
+                final ThingUID thingUID = new ThingUID(thingTypeUID, bridgeUID, stripIdShort(ud.getId()));
+                final Map<String, Object> properties = Map.of(PARAMETER_SITE, ud.getSite().getName(),
+                        PARAMETER_MAC_ADDRESS, ud.getMac());
+                thingDiscovered(DiscoveryResultBuilder.create(thingUID).withThingType(thingTypeUID)
+                        .withBridge(bridgeUID).withRepresentationProperty(PARAMETER_MAC_ADDRESS).withTTL(TTL_SECONDS)
+                        .withProperties(properties).withLabel(ud.getName()).build());
+            }
+        }
+    }
+
     /**
      * Shorten the id to make it a bit more comprehensible.
      *
index cf85fda2973a78f3ce2037c139994c5401629f41..60b14a5f2fdc041f669ec983310d8bee135be224 100644 (file)
                </parameter>
        </config-description>
 
+       <config-description uri="thing-type:unifi:accessPoint">
+               <parameter name="macAddress" type="text" required="true">
+                       <label>Access Point MAC Address</label>
+                       <description>The MAC address of the access point</description>
+               </parameter>
+               <parameter name="site" type="text" required="false">
+                       <label>Site</label>
+                       <description>The site where the access point should be found (optional)</description>
+               </parameter>
+       </config-description>
+
        <config-description uri="channel-type:unifi:poeEnable">
                <parameter name="mode" type="text">
                        <label>On Mode</label>
index d4829cc3a53143402192322a3275d7c55488e487..e6547aa1ccc59cd07b2a362309909bc082cf1ee0 100644 (file)
@@ -5,6 +5,8 @@ addon.unifi.description = The UniFi binding integrates the UniFi controller from
 
 # thing types
 
+thing-type.unifi.accessPoint.label = UniFi Access Point
+thing-type.unifi.accessPoint.description = An access point managed by a UniFi controller
 thing-type.unifi.controller.label = UniFi Controller
 thing-type.unifi.controller.description = A UniFi controller
 thing-type.unifi.poePort.label = UniFi PoE Port
@@ -20,6 +22,10 @@ thing-type.unifi.wlan.description = A UniFi Wireless LAN
 
 # thing types config
 
+thing-type.config.unifi.accessPoint.macAddress.label = Access Point MAC Address
+thing-type.config.unifi.accessPoint.macAddress.description = The MAC address of the access point
+thing-type.config.unifi.accessPoint.site.label = Site
+thing-type.config.unifi.accessPoint.site.description = The site where the access point should be found (optional)
 thing-type.config.unifi.client.cid.label = Client ID
 thing-type.config.unifi.client.cid.description = The MAC address, IP address, hostname or name of the client
 thing-type.config.unifi.client.considerHome.label = Consider Home Interval
@@ -51,6 +57,8 @@ thing-type.config.unifi.wlan.wid.description = The id or name of the wlan
 
 channel-type.unifi.ap.label = Access Point
 channel-type.unifi.ap.description = Access Point the wireless client is connected to
+channel-type.unifi.apEnable.label = Enabled
+channel-type.unifi.apEnable.description = If the access point is enabled
 channel-type.unifi.blocked.label = Blocked
 channel-type.unifi.blocked.description = Is device blocked
 channel-type.unifi.essid.label = Wireless Network
@@ -150,19 +158,6 @@ channel-type.config.unifi.poeEnable.mode.description = The value to set when set
 channel-type.config.unifi.poeEnable.mode.option.auto = Auto
 channel-type.config.unifi.poeEnable.mode.option.pasv24 = 24V
 channel-type.config.unifi.poeEnable.mode.option.passthrough = Passthrough
-channel-type.config.unifi.guestVouchersGenerate.voucherCount.label = Number
-channel-type.config.unifi.guestVouchersGenerate.voucherCount.description = Number of vouchers to create
-channel-type.config.unifi.guestVouchersGenerate.voucherExpiration.label = Expiration Time
-channel-type.config.unifi.guestVouchersGenerate.voucherExpiration.description = Minutes a voucher is valid after activation
-channel-type.config.unifi.guestVouchersGenerate.voucherUsers.label = Users
-channel-type.config.unifi.guestVouchersGenerate.voucherUsers.description = Number of users for voucher, 0 if no limit
-channel-type.config.unifi.guestVouchersGenerate.voucherUpLimit.label = Upload Speed Limit
-channel-type.config.unifi.guestVouchersGenerate.voucherUpLimit.description = Upload speed limit in kbps, no limit if not set
-channel-type.config.unifi.guestVouchersGenerate.voucherDownLimit.label = Download Speed Limit
-channel-type.config.unifi.guestVouchersGenerate.voucherDownLimit.description = Download speed limit in kbps, no limit if not set
-channel-type.config.unifi.guestVouchersGenerate.voucherDataQuota.label = Data Transfer Quota
-channel-type.config.unifi.guestVouchersGenerate.voucherDataQuota.description = Data transfer quota in MB per user, no limit if not set
-channel-type.config.unifi.guestVouchersGenerate.option.GENERATE = Generate
 
 # status messages
 
@@ -177,6 +172,7 @@ error.thing.offline.configuration_error = You must choose a UniFi Controller for
 error.thing.poe.offline.configuration_error = The configuration parameter macAddress must be set and not be empty.
 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
 
 # actions
 
index 1200299420df953551b8fe59d8abf32f24bd25bc..5d096e14c4da950288a419dbf268d82037e82263 100644 (file)
                <config-description-ref uri="thing-type:unifi:poePort"/>
        </thing-type>
 
+       <thing-type id="accessPoint">
+               <supported-bridge-type-refs>
+                       <bridge-type-ref id="controller"/>
+               </supported-bridge-type-refs>
+
+               <label>UniFi Access Point</label>
+               <description>An access point managed by a UniFi controller</description>
+
+               <channels>
+                       <channel id="enable" typeId="apEnable"/>
+               </channels>
+
+               <config-description-ref uri="thing-type:unifi:accessPoint"/>
+       </thing-type>
+
        <!-- Channels -->
 
        <channel-type id="totalClients">
                <state pattern="%.2f %unit%" readOnly="true"/>
        </channel-type>
 
+       <channel-type id="apEnable" advanced="false">
+               <item-type>Switch</item-type>
+               <label>Enabled</label>
+               <description>If the access point is enabled</description>
+       </channel-type>
+
 </thing:thing-descriptions>