mirror of
https://github.com/openhab/openhab-addons.git
synced 2025-01-10 15:11:59 +01:00
[netatmo] Fix doorbell channels flapping (#17367)
* Adressing issue #13002 * Second row of url validity check * Take snapshot expiration in account Signed-off-by: Gaël L'hopital <gael@lhopital.org> Signed-off-by: Ciprian Pascu <contact@ciprianpascu.ro>
This commit is contained in:
parent
233e3ed64b
commit
0334e86c81
@ -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()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
@ -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)) {
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
};
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user