]> git.basschouten.com Git - openhab-addons.git/commitdiff
[netatmo] Fix doorbell channels flapping (#17367)
authorGaël L'hopital <gael@lhopital.org>
Mon, 9 Sep 2024 17:48:06 +0000 (19:48 +0200)
committerGitHub <noreply@github.com>
Mon, 9 Sep 2024 17:48:06 +0000 (19:48 +0200)
* Adressing issue #13002
* Second row of url validity check
* Take snapshot expiration in account

Signed-off-by: Gaël L'hopital <gael@lhopital.org>
bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/api/data/ChannelGroup.java
bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/api/dto/HomeEvent.java
bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/ApiBridgeHandler.java
bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/capability/CameraCapability.java
bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/capability/PersonCapability.java
bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/channelhelper/EventCameraChannelHelper.java
bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/channelhelper/EventChannelHelper.java
bundles/org.openhab.binding.netatmo/src/main/resources/OH-INF/i18n/netatmo.properties

index 5529046ef963333dbd27444a9a9146cf7b08420f..7a69aeb48d3e26f1046f49df907aac9c6b4fb79f 100644 (file)
@@ -90,7 +90,7 @@ public class ChannelGroup {
                     groupTypes.stream().map(NetatmoThingTypeProvider::toGroupName).collect(Collectors.toSet()));
         } catch (ReflectiveOperationException e) {
             throw new IllegalArgumentException(
-                    "Error creating or initializing helper class : %s".formatted(e.getMessage()));
+                    "Error creating or initializing helper class: %s".formatted(e.getMessage()));
         }
     }
 }
index cac51625d7321d3f7b71e7613b83d95e2867f40d..58b3607a0c455026beb14c40a7dd4eb895629046 100644 (file)
@@ -38,6 +38,10 @@ public class HomeEvent extends Event {
     }
 
     private record Snapshot(String url, ZonedDateTime expiresAt) {
+        // If the snapshot is expired we consider it as not available, so do not provide the url
+        public @Nullable String url() {
+            return expiresAt.isAfter(ZonedDateTime.now().withZoneSameInstant(expiresAt.getZone())) ? url : null;
+        }
     }
 
     private ZonedDateTime time = ZonedDateTime.now();
index 4df7a1978c1483e63ddefba8418496c0c04c02b8..cec105c56712e823ab3b2f86100dfb419a4d6679 100644 (file)
@@ -27,7 +27,6 @@ import java.util.Collection;
 import java.util.Deque;
 import java.util.HashMap;
 import java.util.Map;
-import java.util.Objects;
 import java.util.Optional;
 import java.util.Set;
 import java.util.concurrent.ExecutionException;
@@ -183,8 +182,9 @@ public class ApiBridgeHandler extends BaseBridgeHandler {
 
         updateStatus(ThingStatus.ONLINE);
 
-        getThing().getThings().stream().filter(Thing::isEnabled).map(Thing::getHandler).filter(Objects::nonNull)
-                .map(CommonInterface.class::cast).forEach(CommonInterface::expireData);
+        getThing().getThings().stream().filter(Thing::isEnabled).map(Thing::getHandler)
+                .filter(CommonInterface.class::isInstance).map(CommonInterface.class::cast)
+                .forEach(CommonInterface::expireData);
     }
 
     private boolean authenticate(@Nullable String code, @Nullable String redirectUri) {
@@ -353,7 +353,7 @@ public class ApiBridgeHandler extends BaseBridgeHandler {
             throw exception;
         } catch (NetatmoException e) {
             if (e.getStatusCode() == ServiceError.MAXIMUM_USAGE_REACHED) {
-                updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage());
+                updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, "@text/maximum-usage-reached");
                 prepareReconnection(null, null);
             }
             throw e;
index ed16125019798ef2376ba8babaa3efcc24d3d51a..398bd9a876485f18c6f7a9c84e98f7f06b452a6e 100644 (file)
@@ -37,6 +37,7 @@ import org.openhab.binding.netatmo.internal.handler.CommonInterface;
 import org.openhab.binding.netatmo.internal.handler.channelhelper.CameraChannelHelper;
 import org.openhab.binding.netatmo.internal.handler.channelhelper.ChannelHelper;
 import org.openhab.binding.netatmo.internal.providers.NetatmoDescriptionProvider;
+import org.openhab.binding.netatmo.internal.utils.ChannelTypeUtils;
 import org.openhab.core.config.core.Configuration;
 import org.openhab.core.library.types.OnOffType;
 import org.openhab.core.thing.ChannelUID;
@@ -96,9 +97,11 @@ public class CameraCapability extends HomeSecurityThingCapability {
             eventHelper.setUrls(newVpnUrl, localUrl);
         }
         vpnUrl = newVpnUrl;
-        if (!SdCardStatus.SD_CARD_WORKING.equals(newData.getSdStatus())
-                || !AlimentationStatus.ALIM_CORRECT_POWER.equals(newData.getAlimStatus())) {
-            statusReason = "%s, %s".formatted(newData.getSdStatus(), newData.getAlimStatus());
+        if (!SdCardStatus.SD_CARD_WORKING.equals(newData.getSdStatus())) {
+            statusReason = newData.getSdStatus().toString();
+        }
+        if (!AlimentationStatus.ALIM_CORRECT_POWER.equals(newData.getAlimStatus())) {
+            statusReason = newData.getAlimStatus().toString();
         }
     }
 
@@ -125,12 +128,10 @@ public class CameraCapability extends HomeSecurityThingCapability {
     private void updateSubGroup(WebhookEvent event, String group) {
         handler.updateState(group, CHANNEL_EVENT_TYPE, toStringType(event.getEventType()));
         handler.updateState(group, CHANNEL_EVENT_TIME, toDateTimeType(event.getTime()));
-        handler.updateState(group, CHANNEL_EVENT_SNAPSHOT, toRawType(event.getSnapshotUrl()));
-        handler.updateState(group, CHANNEL_EVENT_SNAPSHOT_URL, toStringType(event.getSnapshotUrl()));
-        handler.updateState(group, CHANNEL_EVENT_VIGNETTE, toRawType(event.getVignetteUrl()));
-        handler.updateState(group, CHANNEL_EVENT_VIGNETTE_URL, toStringType(event.getVignetteUrl()));
-        handler.updateState(group, CHANNEL_EVENT_SUBTYPE,
-                Objects.requireNonNull(event.getSubTypeDescription().map(d -> toStringType(d)).orElse(UnDefType.NULL)));
+        updatePictureIfUrlPresent(event.getSnapshotUrl(), group, CHANNEL_EVENT_SNAPSHOT, CHANNEL_EVENT_SNAPSHOT_URL);
+        updatePictureIfUrlPresent(event.getVignetteUrl(), group, CHANNEL_EVENT_VIGNETTE, CHANNEL_EVENT_VIGNETTE_URL);
+        handler.updateState(group, CHANNEL_EVENT_SUBTYPE, Objects.requireNonNull(
+                event.getSubTypeDescription().map(ChannelTypeUtils::toStringType).orElse(UnDefType.NULL)));
         final String message = event.getName();
         handler.updateState(group, CHANNEL_EVENT_MESSAGE,
                 message == null || message.isBlank() ? UnDefType.NULL : toStringType(message));
@@ -139,6 +140,14 @@ public class CameraCapability extends HomeSecurityThingCapability {
         handler.updateState(personChannelUID, personId);
     }
 
+    private void updatePictureIfUrlPresent(@Nullable String snapShotUrl, String group, String pictureChannel,
+            String urlChannel) {
+        if (snapShotUrl != null) {
+            handler.updateState(group, pictureChannel, toRawType(snapShotUrl));
+            handler.updateState(group, urlChannel, toStringType(snapShotUrl));
+        }
+    }
+
     @Override
     public void handleCommand(String channelName, Command command) {
         if (command instanceof OnOffType && CHANNEL_MONITORING.equals(channelName)) {
index 60b9f3fe51175ffae6f97f0fe0dfc09f264216e2..da41d6444b28747b01860bfff42bd05563de3298 100644 (file)
@@ -34,6 +34,7 @@ import org.openhab.binding.netatmo.internal.api.dto.WebhookEvent;
 import org.openhab.binding.netatmo.internal.handler.CommonInterface;
 import org.openhab.binding.netatmo.internal.handler.channelhelper.ChannelHelper;
 import org.openhab.binding.netatmo.internal.providers.NetatmoDescriptionProvider;
+import org.openhab.binding.netatmo.internal.utils.ChannelTypeUtils;
 import org.openhab.core.library.types.OnOffType;
 import org.openhab.core.thing.ChannelUID;
 import org.openhab.core.types.Command;
@@ -79,8 +80,8 @@ public class PersonCapability extends HomeSecurityThingCapability {
     protected void updateWebhookEvent(WebhookEvent event) {
         super.updateWebhookEvent(event);
 
-        handler.updateState(GROUP_LAST_EVENT, CHANNEL_EVENT_SUBTYPE,
-                Objects.requireNonNull(event.getSubTypeDescription().map(d -> toStringType(d)).orElse(UnDefType.NULL)));
+        handler.updateState(GROUP_LAST_EVENT, CHANNEL_EVENT_SUBTYPE, Objects.requireNonNull(
+                event.getSubTypeDescription().map(ChannelTypeUtils::toStringType).orElse(UnDefType.NULL)));
 
         final String message = event.getName();
         handler.updateState(GROUP_LAST_EVENT, CHANNEL_EVENT_MESSAGE,
index 6348ea1d45141d39f46739ef83127f9b86521955..7283ec3955c41269f6e15f82cab478d53cd369e2 100644 (file)
@@ -13,7 +13,7 @@
 package org.openhab.binding.netatmo.internal.handler.channelhelper;
 
 import static org.openhab.binding.netatmo.internal.NetatmoBindingConstants.*;
-import static org.openhab.binding.netatmo.internal.utils.ChannelTypeUtils.*;
+import static org.openhab.binding.netatmo.internal.utils.ChannelTypeUtils.toStringType;
 
 import java.util.Set;
 
@@ -43,10 +43,10 @@ public class EventCameraChannelHelper extends EventChannelHelper {
                 case CHANNEL_EVENT_TYPE -> toStringType(event.getEventType());
                 case CHANNEL_EVENT_TIME -> new DateTimeType(event.getTime());
                 case CHANNEL_EVENT_MESSAGE -> toStringType(event.getName());
-                case CHANNEL_EVENT_SNAPSHOT -> toRawType(event.getSnapshotUrl());
-                case CHANNEL_EVENT_SNAPSHOT_URL -> toStringType(event.getSnapshotUrl());
-                case CHANNEL_EVENT_VIGNETTE -> toRawType(event.getVignetteUrl());
-                case CHANNEL_EVENT_VIGNETTE_URL -> toStringType(event.getVignetteUrl());
+                case CHANNEL_EVENT_SNAPSHOT -> checkUrlPresence(event.getSnapshotUrl(), true);
+                case CHANNEL_EVENT_SNAPSHOT_URL -> checkUrlPresence(event.getSnapshotUrl(), false);
+                case CHANNEL_EVENT_VIGNETTE -> checkUrlPresence(event.getVignetteUrl(), true);
+                case CHANNEL_EVENT_VIGNETTE_URL -> checkUrlPresence(event.getVignetteUrl(), false);
                 default -> super.internalGetHomeEvent(channelId, groupId, event);
             };
         }
index 947e47bf5a4487523bb9ad01d229f0e41488954e..afbb4cea702eaea33bf2214b6d53b2aa543d9e7c 100644 (file)
@@ -72,17 +72,24 @@ public class EventChannelHelper extends ChannelHelper {
             case CHANNEL_EVENT_CAMERA_ID -> toStringType(event.getCameraId());
             case CHANNEL_EVENT_SUBTYPE ->
                 event.getSubTypeDescription().map(ChannelTypeUtils::toStringType).orElse(UnDefType.NULL);
-            case CHANNEL_EVENT_SNAPSHOT -> toRawType(event.getSnapshotUrl());
-            case CHANNEL_EVENT_SNAPSHOT_URL -> toStringType(event.getSnapshotUrl());
+            case CHANNEL_EVENT_SNAPSHOT -> checkUrlPresence(event.getSnapshotUrl(), true);
+            case CHANNEL_EVENT_SNAPSHOT_URL -> checkUrlPresence(event.getSnapshotUrl(), false);
             default -> null;
         };
     }
 
+    protected @Nullable State checkUrlPresence(@Nullable String url, boolean asRaw) {
+        return url != null ? asRaw ? toRawType(url) : toStringType(url) : null;
+    }
+
     @Override
     protected @Nullable State internalGetHomeEvent(String channelId, @Nullable String groupId, HomeEvent event) {
+        String videoId = event.getVideoId();
+        if (videoId == null) {
+            return null;
+        }
         return switch (channelId) {
-            case CHANNEL_EVENT_VIDEO_STATUS ->
-                event.getVideoId() != null ? toStringType(event.getVideoStatus()) : UnDefType.NULL;
+            case CHANNEL_EVENT_VIDEO_STATUS -> toStringType(event.getVideoStatus());
             case CHANNEL_EVENT_VIDEO_LOCAL_URL -> getStreamURL(true, event.getVideoId(), event.getVideoStatus());
             case CHANNEL_EVENT_VIDEO_VPN_URL -> getStreamURL(false, event.getVideoId(), event.getVideoStatus());
             default -> null;
index 7df9236505b256789ff2977b47f375f8ee77dbed..820a91b98e732348845f06211ef93e58e62701d5 100644 (file)
@@ -465,6 +465,7 @@ device-not-connected = Thing is not reachable
 data-over-limit = Data seems quite old
 request-time-out = Request timed out - will attempt reconnection later
 deserialization-unknown = Deserialization lead to an unknown code
+maximum-usage-reached = Maximum usage reached. Will try reconnection after `reconnectInterval` seconds.
 
 homestatus-unknown-error = Unknown error
 homestatus-internal-error = Internal error