From 0560a0e333c3d7a1c26c2c4c9dfb658d35b03d11 Mon Sep 17 00:00:00 2001 From: Hilbrand Bouwkamp Date: Mon, 3 Oct 2022 13:02:46 +0200 Subject: [PATCH] [unifi] Detect all PoE ports, and set PoE thing offline if no data could be found (#13455) * [unifi] Set PoE thing offline if no data could be found This would better reflect the PoE thing status if there is a problem with either the data from the api or a configuration problem (like invalid port number). * [unifi] Fix bug to detect PoE ports when first port is not PoE port The binding assumed either all ports or no ports were PoE, and asssumed if port 0 was not PoE none was PoE. However, some switches have ports starting at port 5 to be PoE. Therefor changed code to just test each port if it is PoE. Signed-off-by: Hilbrand Bouwkamp --- .../api/cache/UniFiControllerCache.java | 27 +++++++++---------- .../handler/UniFiPoePortThingHandler.java | 19 ++++++++++--- .../resources/OH-INF/i18n/unifi.properties | 1 + 3 files changed, 29 insertions(+), 18 deletions(-) diff --git a/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/cache/UniFiControllerCache.java b/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/cache/UniFiControllerCache.java index e8189ddaa8c..698cb42b8fb 100644 --- a/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/cache/UniFiControllerCache.java +++ b/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/cache/UniFiControllerCache.java @@ -26,6 +26,7 @@ import org.eclipse.jdt.annotation.Nullable; import org.openhab.binding.unifi.internal.api.dto.UnfiPortOverrideJsonElement; 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.UniFiPortTable; 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.UniFiWlan; @@ -93,25 +94,23 @@ public class UniFiControllerCache { devicesCache.putAll(devices); if (devices != null) { Stream.of(devices).filter(Objects::nonNull).forEach(d -> { - Stream.ofNullable(d.getPortTable()).filter(ptl -> ptl.length > 0 && ptl[0].isPortPoe()).forEach(pt -> { - final Map tupleTable = devicesToPortTables.computeIfAbsent(d.getMac(), - p -> new HashMap<>()); + Stream.ofNullable(d.getPortTable()).flatMap(pt -> Stream.of(pt)).filter(UniFiPortTable::isPortPoe) + .forEach(p -> { + final Map tupleTable = devicesToPortTables + .computeIfAbsent(d.getMac(), tt -> new HashMap<>()); + final UniFiPortTuple tuple = tupleTable.computeIfAbsent(p.getPortIdx(), + t -> new UniFiPortTuple()); - Stream.of(pt).forEach(p -> { - final UniFiPortTuple tuple = tupleTable.computeIfAbsent(p.getPortIdx(), - t -> new UniFiPortTuple()); - - tuple.setDevice(d); - tuple.setTable(p); - }); - }); - Stream.ofNullable(d.getPortOverrides()).filter(ptl -> ptl.length > 0).forEach(po -> { + tuple.setDevice(d); + tuple.setTable(p); + }); + Stream.ofNullable(d.getPortOverrides()).forEach(po -> { final Map tupleTable = devicesToPortTables.get(d.getMac()); if (tupleTable != null) { Stream.of(po).filter(pof -> !pof.getAsJsonObject().entrySet().isEmpty()) - .map(UnfiPortOverrideJsonElement::new) - .forEach(p -> tupleTable.get(p.getPortIdx()).setJsonElement(p)); + .map(UnfiPortOverrideJsonElement::new).forEach(p -> tupleTable + .computeIfAbsent(p.getPortIdx(), t -> new UniFiPortTuple()).setJsonElement(p)); } }); }); diff --git a/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/handler/UniFiPoePortThingHandler.java b/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/handler/UniFiPoePortThingHandler.java index e0edb5d3709..90501cb7927 100644 --- a/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/handler/UniFiPoePortThingHandler.java +++ b/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/handler/UniFiPoePortThingHandler.java @@ -98,12 +98,15 @@ public class UniFiPoePortThingHandler @Override protected State getChannelState(final Map ports, final String channelId) { - final UniFiPortTable port = getPort(ports).getTable(); + final UniFiPortTuple portTuple = getPort(ports); + + if (portTuple == null) { + return setOfflineOnNoPoEPortData(); + } + final UniFiPortTable port = portTuple.getTable(); if (port == null) { - logger.debug("No PoE port for thing '{}' could be found in the data. Refresh ignored.", - getThing().getUID()); - return UnDefType.NULL; + return setOfflineOnNoPoEPortData(); } final State state; @@ -132,6 +135,14 @@ public class UniFiPoePortThingHandler return state; } + private State setOfflineOnNoPoEPortData() { + if (getThing().getStatus() != ThingStatus.OFFLINE) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, + "@text/error.thing.poe.offline.nodata_error"); + } + return UnDefType.NULL; + } + private @Nullable UniFiPortTuple getPort(final Map ports) { return ports.get(config.getPortNumber()); } diff --git a/bundles/org.openhab.binding.unifi/src/main/resources/OH-INF/i18n/unifi.properties b/bundles/org.openhab.binding.unifi/src/main/resources/OH-INF/i18n/unifi.properties index b8c2d0e0e05..cc8e3d5c076 100644 --- a/bundles/org.openhab.binding.unifi/src/main/resources/OH-INF/i18n/unifi.properties +++ b/bundles/org.openhab.binding.unifi/src/main/resources/OH-INF/i18n/unifi.properties @@ -140,4 +140,5 @@ error.thing.client.offline.configuration_error = You must define a MAC address, error.thing.offline.bridge_offline = The UniFi Controller is currently offline. error.thing.offline.configuration_error = You must choose a UniFi Controller for this thing. 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.