From 83e0ccbee0bb748d01f1dcc5209c27da5fe1abe4 Mon Sep 17 00:00:00 2001 From: clinique Date: Tue, 4 Oct 2022 15:10:46 +0200 Subject: [PATCH] Buffer last event requests per child modules This is targetted to decrease the number of requests transmitted to Netatmo API. Solves #13358 Signed-off-by: clinique --- .../netatmo/internal/api/SecurityApi.java | 32 +++++----- .../handler/capability/CameraCapability.java | 6 +- .../handler/capability/HomeCapability.java | 2 +- .../handler/capability/PersonCapability.java | 7 +-- .../capability/SecurityCapability.java | 58 ++++++++++++++++++- .../handler/capability/SmokeCapability.java | 7 +-- 6 files changed, 79 insertions(+), 33 deletions(-) diff --git a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/api/SecurityApi.java b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/api/SecurityApi.java index bbb9038bfe903..6a1e22490a69d 100644 --- a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/api/SecurityApi.java +++ b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/api/SecurityApi.java @@ -16,11 +16,11 @@ import java.net.URI; import java.util.Collection; -import java.util.stream.Collectors; import javax.ws.rs.core.UriBuilder; import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; import org.openhab.binding.netatmo.internal.api.data.NetatmoConstants.FeatureArea; import org.openhab.binding.netatmo.internal.api.data.NetatmoConstants.FloodLightMode; import org.openhab.binding.netatmo.internal.api.dto.Home; @@ -62,33 +62,29 @@ public boolean addwebhook(URI uri) throws NetatmoException { return true; } - public Collection getPersonEvents(String homeId, String personId) throws NetatmoException { - UriBuilder uriBuilder = getApiUriBuilder(SUB_PATH_GET_EVENTS, PARAM_HOME_ID, homeId, PARAM_PERSON_ID, personId, - PARAM_OFFSET, 1); - NAEventsDataResponse response = get(uriBuilder, NAEventsDataResponse.class); - BodyResponse body = response.getBody(); + private Collection getEvents(@Nullable Object... params) throws NetatmoException { + UriBuilder uriBuilder = getApiUriBuilder(SUB_PATH_GET_EVENTS, params); + BodyResponse body = get(uriBuilder, NAEventsDataResponse.class).getBody(); if (body != null) { Home home = body.getElement(); if (home != null) { - return home.getEvents().stream().filter(event -> personId.equals(event.getPersonId())) - .collect(Collectors.toList()); + return home.getEvents(); } } throw new NetatmoException("home should not be null"); } + public Collection getHomeEvents(String homeId) throws NetatmoException { + return getEvents(PARAM_HOME_ID, homeId); + } + + public Collection getPersonEvents(String homeId, String personId) throws NetatmoException { + return getEvents(PARAM_HOME_ID, homeId, PARAM_PERSON_ID, personId, PARAM_OFFSET, 1); + } + public Collection getDeviceEvents(String homeId, String deviceId, String deviceType) throws NetatmoException { - UriBuilder uriBuilder = getApiUriBuilder(SUB_PATH_GET_EVENTS, PARAM_HOME_ID, homeId, PARAM_DEVICE_ID, deviceId, - PARAM_DEVICES_TYPE, deviceType); - BodyResponse body = get(uriBuilder, NAEventsDataResponse.class).getBody(); - if (body != null) { - Home home = body.getElement(); - if (home != null) { - return home.getEvents(); - } - } - throw new NetatmoException("home should not be null"); + return getEvents(PARAM_HOME_ID, homeId, PARAM_DEVICE_ID, deviceId, PARAM_DEVICES_TYPE, deviceType); } public String ping(String vpnUrl) throws NetatmoException { diff --git a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/capability/CameraCapability.java b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/capability/CameraCapability.java index 7c526b3cc05d4..224198bf9de3d 100644 --- a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/capability/CameraCapability.java +++ b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/capability/CameraCapability.java @@ -15,7 +15,6 @@ import static org.openhab.binding.netatmo.internal.NetatmoBindingConstants.*; import java.util.ArrayList; -import java.util.Collection; import java.util.List; import java.util.stream.Collectors; @@ -97,9 +96,8 @@ protected void beforeNewData() { public List updateReadings() { List result = new ArrayList<>(); securityCapability.ifPresent(cap -> { - Collection events = cap.getDeviceEvents(handler.getId(), moduleType.apiName); - if (!events.isEmpty()) { - HomeEvent event = events.iterator().next(); + HomeEvent event = cap.getLastDeviceEvent(handler.getId(), moduleType.apiName); + if (event != null) { result.add(event); result.addAll(event.getSubevents()); } diff --git a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/capability/HomeCapability.java b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/capability/HomeCapability.java index 0e001bafd435a..045a368be2572 100644 --- a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/capability/HomeCapability.java +++ b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/capability/HomeCapability.java @@ -113,7 +113,7 @@ protected List updateReadings(HomeApi api) { result.add(homeStatus); } } catch (NetatmoException e) { - logger.warn("Error gettting Home informations : {}", e.getMessage()); + logger.warn("Error getting Home informations : {}", e.getMessage()); } return result; } diff --git a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/capability/PersonCapability.java b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/capability/PersonCapability.java index f03d1306f83d4..aa88faaca5537 100644 --- a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/capability/PersonCapability.java +++ b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/capability/PersonCapability.java @@ -16,7 +16,6 @@ import java.time.ZonedDateTime; import java.util.ArrayList; -import java.util.Collection; import java.util.List; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -90,9 +89,9 @@ public void updateEvent(Event event) { public List updateReadings() { List result = new ArrayList<>(); securityCapability.ifPresent(cap -> { - Collection events = cap.getPersonEvents(handler.getId()); - if (!events.isEmpty()) { - result.add(events.iterator().next()); + HomeEvent event = cap.getLastPersonEvent(handler.getId()); + if (event != null) { + result.add(event); } }); return result; diff --git a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/capability/SecurityCapability.java b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/capability/SecurityCapability.java index 6fa9661e5728f..af56fdca34ae5 100644 --- a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/capability/SecurityCapability.java +++ b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/capability/SecurityCapability.java @@ -12,8 +12,11 @@ */ package org.openhab.binding.netatmo.internal.handler.capability; +import java.util.ArrayList; import java.util.Collection; +import java.util.HashMap; import java.util.List; +import java.util.Map; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; @@ -27,6 +30,7 @@ import org.openhab.binding.netatmo.internal.api.dto.HomeStatusModule; import org.openhab.binding.netatmo.internal.api.dto.HomeStatusPerson; import org.openhab.binding.netatmo.internal.api.dto.NAHomeStatus.HomeStatus; +import org.openhab.binding.netatmo.internal.api.dto.NAObject; import org.openhab.binding.netatmo.internal.deserialization.NAObjectMap; import org.openhab.binding.netatmo.internal.handler.CommonInterface; import org.slf4j.Logger; @@ -42,6 +46,8 @@ class SecurityCapability extends RestCapability { private final Logger logger = LoggerFactory.getLogger(SecurityCapability.class); + private static final Map eventBuffer = new HashMap<>(); + SecurityCapability(CommonInterface handler) { super(handler, SecurityApi.class); } @@ -110,7 +116,55 @@ protected void updateHomeEvent(HomeEvent homeEvent) { }); } - public Collection getDeviceEvents(String cameraId, String deviceType) { + @Override + protected List updateReadings(SecurityApi api) { + List result = new ArrayList<>(); + try { + Collection lastEvents = api.getHomeEvents(handler.getId()); + lastEvents.stream().forEach(event -> { + HomeEvent previousEvent = eventBuffer.get(event.getCameraId()); + if (previousEvent == null || previousEvent.getTime().isBefore(event.getTime())) { + eventBuffer.put(event.getCameraId(), event); + } + String personId = event.getPersonId(); + if (personId != null) { + previousEvent = eventBuffer.get(personId); + if (previousEvent == null || previousEvent.getTime().isBefore(event.getTime())) { + eventBuffer.put(personId, event); + } + } + }); + } catch (NetatmoException e) { + logger.warn("Error retrieving last events for home '{}' : {}", handler.getId(), e.getMessage()); + } + return result; + } + + public @Nullable HomeEvent getLastPersonEvent(String personId) { + HomeEvent event = eventBuffer.get(personId); + if (event == null) { + Collection events = requestPersonEvents(personId); + if (!events.isEmpty()) { + event = events.iterator().next(); + eventBuffer.put(personId, event); + } + } + return event; + } + + public @Nullable HomeEvent getLastDeviceEvent(String cameraId, String deviceType) { + HomeEvent event = eventBuffer.get(cameraId); + if (event == null) { + Collection events = requestDeviceEvents(cameraId, deviceType); + if (!events.isEmpty()) { + event = events.iterator().next(); + eventBuffer.put(cameraId, event); + } + } + return event; + } + + private Collection requestDeviceEvents(String cameraId, String deviceType) { return getApi().map(api -> { try { return api.getDeviceEvents(handler.getId(), cameraId, deviceType); @@ -121,7 +175,7 @@ public Collection getDeviceEvents(String cameraId, String deviceType) }).orElse(List.of()); } - public Collection getPersonEvents(String personId) { + private Collection requestPersonEvents(String personId) { return getApi().map(api -> { try { return api.getPersonEvents(handler.getId(), personId); diff --git a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/capability/SmokeCapability.java b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/capability/SmokeCapability.java index be188f1d07871..560bc3b7e7ad4 100644 --- a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/capability/SmokeCapability.java +++ b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/capability/SmokeCapability.java @@ -13,7 +13,6 @@ package org.openhab.binding.netatmo.internal.handler.capability; import java.util.ArrayList; -import java.util.Collection; import java.util.List; import org.eclipse.jdt.annotation.NonNullByDefault; @@ -41,9 +40,9 @@ public SmokeCapability(CommonInterface handler, NetatmoDescriptionProvider descr public List updateReadings() { List result = new ArrayList<>(); securityCapability.ifPresent(cap -> { - Collection events = cap.getDeviceEvents(handler.getId(), moduleType.apiName); - if (!events.isEmpty()) { - result.add(events.iterator().next()); + HomeEvent event = cap.getLastDeviceEvent(handler.getId(), moduleType.apiName); + if (event != null) { + result.add(event); } }); return result;